home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 23 / AMIGAplus Sonderheft 23 (2000)(Falke)(DE)[!].iso / PublicDomain / Anwendungen / db3.6-beta-src / db.c < prev    next >
C/C++ Source or Header  |  1998-01-16  |  116KB  |  3,276 lines

  1.  
  2. /**********************************************************************/
  3. /*                              Includes                              */
  4. /**********************************************************************/
  5.  
  6. #include <stdio.h>
  7. #include <time.h>
  8. #include <dos.h>        /* For getpath() */
  9. #include <dos/stdio.h>
  10. #include <stdlib.h>     /* qsort ... */
  11. #include <string.h>
  12. #include <ctype.h>
  13.  
  14. #include <exec/types.h>
  15. #include <exec/memory.h>
  16. #include <exec/ports.h>
  17. #include <clib/alib_protos.h>           /* NewList() */
  18. #include <intuition/intuition.h>
  19. #include <intuition/classes.h>
  20. #include <intuition/classusr.h>
  21. #include <intuition/imageclass.h>
  22. #include <intuition/gadgetclass.h>
  23. #include <gadgets/textfield.h>
  24.  
  25. #include <workbench/workbench.h>        /* For the project icon creation */
  26. #include <workbench/startup.h> /* For the project icon start */
  27. #include <libraries/asl.h>
  28. #include <libraries/gadtools.h>
  29. #include <libraries/commodities.h> /* This has a nice qualifier #define */
  30. #include <libraries/iffparse.h>
  31. #include <devices/serial.h>     /* For dialing */
  32. #include <datatypes/textclass.h>        /* This has defines for IFF IDs */
  33. #include <graphics/displayinfo.h>
  34. #include <graphics/gfxbase.h>
  35. #include <graphics/text.h>
  36. #include <proto/exec.h>
  37. #include <proto/dos.h>
  38. #include <proto/intuition.h>
  39. #include <proto/gadtools.h>
  40. #include <proto/iffparse.h>
  41. #include <proto/graphics.h>
  42. #include <proto/utility.h>
  43. #include <proto/icon.h>
  44. #include <proto/asl.h>
  45. #include <proto/wb.h>
  46. #include <proto/diskfont.h>
  47. #include <proto/textfield.h>
  48. #include <clib/alib_protos.h>
  49.  
  50. #include "dbGUI.h"
  51. #include "db.h"
  52. #include "dbparser.h"
  53. #include "dbtexts.h"
  54. #include "Select.h"
  55. #include "dbRexx.h"
  56. #include "Design.h"
  57. #include "Version.h"
  58.  
  59. /**********************************************************************/
  60. /*                              Defines                               */
  61. /**********************************************************************/
  62.  
  63. #ifdef LATTICE
  64. void __regargs __chkabort(void); /* Disable SAS CTRL/C handling */
  65. void __regargs __chkabort(void) {} /* One may also use the nocheckabort flag */
  66. #endif
  67.  
  68. #define MY_FILE_BUF 65536
  69.  
  70. /* Argument to DoSort() offset */ 
  71. #define NORMAL_SORT -1
  72. #define UNSORT -2
  73.  
  74. /**********************************************************************/
  75. /*                              Globals                               */
  76. /**********************************************************************/
  77.  
  78.  /* For correct 'Default Tool' in icons */
  79.  
  80. char ProgramDirAndName[FMSIZE];
  81.  
  82. LONG WinSig = 0; /* For IDCMP handling */
  83.  
  84. struct TextFont *UserTextFont = NULL;   /* Global so OpenLayWin() can check */
  85.                                                                                                         /* If this font should be used */
  86.  
  87. struct Pro *FirstPro = NULL;
  88. struct Pro *CurrentPro = NULL;
  89.  
  90. /* For ReadArgs() */
  91.  
  92. UBYTE SerialUnit = 0;
  93. UBYTE DialSpeed = 4;
  94. int UserFontYSize = -1; /* Illegal height defaults to screen font */
  95.  
  96. struct RDArgs *MyRDArgs = NULL;         /* Shell arguments hook */
  97. UBYTE **TTypes = NULL;                                  /* WB ToolTypes hook */
  98.  
  99. UBYTE MyTemplate[] = "Files/M,DEVICE=DEV/K,UNIT/K/N,DIALPREFIX=DPRE/K,DIALPOSTFIX=DPOST/K,"
  100.  "AREACODE=AC/K,PUBSCREEN=PUB/K,FONTNAME=FNAME/K,FONTSIZE=FSIZE/K/N,NOICONS/S,NOSPEEDRENDER=NSR/S,"
  101.  "NORETURNSTEP=NRS/S,NOSERIAL/S,HORIZBAR/S,ESCQUIT/S,TONEDIAL/S,"
  102.  "TONEDIALSPEED=TONE/K/N,CCITT5/S,MAKEBACKUP=BACK/S,LOCALESORT=LS/S,HIGHLABEL=HI/S,NOBORDER=NB/S,"
  103.  "DEFPATTERN=DP/K,DEFREXXPATTERN=DRP/K";
  104.  
  105. #define _DEFPATTERN     "#?"
  106. #define _DEFREXXPATTERN "#?.(db|rexxdb)"
  107.  
  108. LONG MyArgArray[] = {
  109.         NULL,
  110.         (LONG)"serial.device",
  111.         (LONG)&SerialUnit,
  112.         (LONG)"ATDT ",
  113.         (LONG)";H\r",
  114.         (LONG)"",
  115.         (LONG) NULL,
  116.         (LONG)"",
  117.         (LONG)&UserFontYSize,
  118.         FALSE,
  119.         FALSE,
  120.         FALSE,
  121.         FALSE,
  122.         FALSE,
  123.         FALSE,
  124.         FALSE,
  125.         (LONG)&DialSpeed,
  126.         FALSE,
  127.         FALSE,
  128.         FALSE,
  129.         FALSE,
  130.         FALSE,
  131.         (LONG)_DEFPATTERN,
  132.         (LONG)_DEFREXXPATTERN
  133. };
  134.  
  135. /*
  136.  
  137. LONG PrefsArgArray[] = {
  138.         NULL,
  139.         (LONG)"serial.device",
  140.         (LONG)&SerialUnit,
  141.         (LONG)"ATDT ",
  142.         (LONG)";H\r",
  143.         (LONG)"",
  144.         (LONG) NULL,
  145.         (LONG)"",
  146.         (LONG)&UserFontYSize,
  147.         FALSE,
  148.         FALSE,
  149.         FALSE,
  150.         FALSE,
  151.         FALSE,
  152.         FALSE,
  153.         FALSE,
  154.         (LONG)&DialSpeed,
  155.         FALSE,
  156.         FALSE,
  157.         FALSE,
  158.         FALSE,
  159.         FALSE,
  160.         (LONG)_DEFPATTERN,
  161.         (LONG)_DEFREXXPATTERN
  162. };
  163.  
  164. */
  165. /* ASL tags */
  166.  
  167. char EmptyString[]="";
  168.  
  169. struct TagItem frtags[] =
  170. {
  171.     ASLFR_InitialHeight,        MYHEIGHT,
  172.     ASLFR_InitialWidth,         MYWIDTH,
  173.     ASLFR_InitialLeftEdge,      MYLEFTEDGE,
  174.     ASLFR_InitialTopEdge,       MYTOPEDGE,
  175. //    ASLFR_InitialPattern,       "#?",
  176.     ASLFR_DoPatterns,           TRUE,
  177.     ASLFR_RejectIcons,          TRUE,
  178.     TAG_DONE
  179. };
  180.  
  181. struct LocaleInfo LocaleInfo = {        NULL, NULL };
  182. struct Locale *MyLocale = NULL;
  183.  
  184.  
  185. /* Global Prefs settings.. */
  186.  
  187. BOOL DisplayWarnings = TRUE;
  188.  
  189. /* sorting stuff */
  190.  
  191. BOOL AutoSort = FALSE;
  192.  
  193. typedef int (*CompFunc)(char *, char *);
  194.  
  195. struct SortOrder {
  196.         short Order;
  197.         short Offset;
  198.         CompFunc CmpFunc;       /* numeric fieldtypes require other sort functions */
  199. };
  200.         
  201. struct SortInfo {
  202.         struct SortOrder *so;
  203.         size_t norders;
  204.         char SortDir;
  205.         BOOL UnSort;    /* Sort the database based upon each record's address instead */
  206. } SI = { NULL, 0, SORT_DIR_AZ, FALSE };
  207.  
  208.  
  209. /* AppWindow specifics */
  210. struct MsgPort *AWPort =  NULL;
  211. /* End of AppWindow specifics */
  212.  
  213.  
  214. /* Security variables */
  215. char UserName[50] = "«No keyfile needed»";
  216. int UserID = 0;
  217.  
  218. /* For the serial device used in dialing*/
  219. struct MsgPort *SerialMP = NULL;
  220. struct IOExtSer *SerialIO = NULL;
  221.  
  222.  
  223. /* For the clipboard */
  224. struct IFFHandle *Iff0 = NULL, *Iff1 = NULL;
  225.  
  226. BOOL PassWordOk = TRUE; /* Security */
  227.  
  228. struct Library *RexxSysBase = NULL;
  229. struct Library *LocaleBase = NULL;
  230. struct Library *DiskfontBase = NULL;
  231. struct Library *IFFParseBase = NULL;
  232. struct Library *IconBase = NULL;
  233. struct Library *CxBase = NULL;
  234. struct Library *AslBase = NULL;
  235. struct GfxBase *GfxBase = NULL;
  236. struct IntuitionBase *IntuitionBase = NULL;
  237. struct Library *GadToolsBase = NULL;
  238. struct Library *UtilityBase = NULL;
  239. struct Library *WorkbenchBase = NULL;   /* For AppWindow */
  240. struct Library *TextFieldBase = NULL;
  241. Class *TextFieldClass = NULL;
  242.  
  243.  
  244. /**********************************************************************/
  245. /*                             Prototypes                             */
  246. /**********************************************************************/
  247.  
  248.  
  249. /**********************************************************************/
  250. /*                             Functions                              */
  251. /**********************************************************************/
  252.  
  253.  
  254. LONG EasyLocRequest(struct Window *w, struct EasyStruct *es, ULONG *idcmp,
  255.  APTR arg1, ...)
  256. {
  257.         /* Displays an EasyRequest where the strings are locale string-indexes */
  258.         LONG ret_val;
  259.         struct EasyStruct nes;
  260.         nes.es_StructSize = sizeof(struct EasyStruct);
  261.         nes.es_Flags = 0;
  262.         nes.es_Title = GetAppStr((LONG)es->es_Title);
  263.         nes.es_TextFormat = GetAppStr((LONG)es->es_TextFormat);
  264.         nes.es_GadgetFormat = GetAppStr((LONG)es->es_GadgetFormat);
  265.         
  266.         if (w) BlockInput(w, TRUE);
  267.         ret_val = EasyRequestArgs(w, &nes, idcmp, &arg1);
  268.         if (w) FreeInput(w);
  269.         return ret_val;
  270. }
  271.  
  272.  
  273. void ShowError(int errnum, char *text)
  274. {
  275.         struct Window *w;
  276.         if (errnum >= 0) return;
  277.         if (CurrentPro->CurrentLayout) w = CurrentPro->CurrentLayout->Window;
  278.  
  279.         switch (errnum) {
  280.                 case MEM_ERR:
  281.                         EasyLocRequest(w, &ES_MemWarn, NULL, text);
  282.                         break;
  283.                 case RFF_ERR:
  284.                         EasyLocRequest(w, &ES_MangledRFF, NULL, text);
  285.                         break;
  286.                 case FILE_ERR:
  287.                         EasyLocRequest(w, &ES_WrongFileType, NULL, text);
  288.                         break;
  289.                 case GAD_ERR:
  290.                 case WIN_ERR:
  291.                 case MENU_ERR:
  292.                         EasyLocRequest(w, &ES_WinOpenErr, NULL, NULL);
  293.                         break;
  294.                 case WINSIZE_ERR:
  295.                         EasyLocRequest(w, &ES_WinSizeErr, NULL, NULL);
  296.                         break;
  297.                 default:
  298.                         EasyLocRequest(w, &ES_DefaultErr, NULL, NULL);
  299.                         break;
  300.         }
  301. }
  302.  
  303. BOOL JumpList(struct Pro *Pr, int delta)
  304. {
  305.         int newnum = Pr->RecNum+delta;
  306.         struct Rec *rp = Pr->CurrentRec;
  307.  
  308.         if (newnum >= Pr->RecSum || newnum < 0) return FALSE;           /* Outside */
  309.  
  310.         Pr->RecNum = newnum;            /* First correct the record number */
  311.  
  312.         if (delta>0) while (delta) { rp=rp->Next; delta--; }
  313.         else while (delta) { rp=rp->Prev; delta++; }
  314.         Pr->CurrentRec = rp;
  315.         return TRUE;
  316.  
  317. }
  318.  
  319. Field GetFld(struct Rec *crp, short Offset)
  320. {
  321.         if (!crp->Fields || Offset >= crp->FldSum) return EmptyString;
  322.         return crp->Fields[Offset];
  323. }
  324.  
  325.  
  326. /* Functions to support reading and updating arbitrary fieldtypes */
  327.  
  328. unsigned char *convertLF(unsigned char *s)
  329. {
  330.         unsigned char *start;
  331.         for (start = s; *s; s++) {
  332.                 if (*s == '\n') *s = 0xb6;      /* The paragraph character */
  333.                 else if (*s == 0xb6) *s = '\n';
  334.         }
  335.         return s;
  336. }
  337.  
  338. char *ReadVisFld(struct Pro *Pr, struct VisFldInfo *vf)
  339. /* CheckBox and CycleGadgets that are disabled  return empty string  */
  340. {
  341. //      static char returnstring[10];           /* All VisFld's shall return strings */
  342.         static char returnstring[10000];                /* All VisFld's shall return strings */
  343.         char *s;
  344.         ULONG size;
  345.  
  346.         if (!vf) return EmptyString;            /* Safety */
  347.  
  348.         switch (vf->Gadget->GadgetID) {
  349.                 case STRING_KIND :
  350.                         return (char *)GetStr(vf->Gadget);
  351.                         break;  
  352.                 case TEXT_KIND :
  353.                         return GetFld(*Pr->Recpp, vf->Offset);
  354.                         break;
  355.                         
  356.                 case CHECKBOX_KIND :
  357.                 case CYCLE_KIND :
  358.                         if (vf->Gadget->Flags & GFLG_DISABLED) return EmptyString;
  359.                         stci_d(returnstring, vf->Code);
  360.                         return returnstring;
  361.                         break;
  362.                 case TEXTFIELD_KIND :
  363.                         OffGadget(vf->Gadget, Pr->CurrentLayout->Window, NULL);
  364.                         GetAttr(TEXTFIELD_Size, vf->Gadget, (ULONG *)&size);
  365.                         GetAttr(TEXTFIELD_Text, vf->Gadget, (ULONG *)&s);
  366.                         OnGadget(vf->Gadget, Pr->CurrentLayout->Window, NULL);
  367.                         if (size) {
  368.                                 stccpy(returnstring, s, size+1);
  369.                                 convertLF(returnstring);
  370.                                 return returnstring;
  371.                         } else return EmptyString;
  372.                         break;
  373.         }
  374. }
  375.  
  376. char *CodeToText(struct VisFldInfo *vf, char *s)
  377. /* For vf:s of string kind, returns s */
  378. /* For vf:s of checkbox returns space or X */
  379. /* For vf:s of cycle kind returns full text */
  380. /* CheckBox and CycleGadgets that are disabled  return empty string  */
  381. {
  382.         static char returnstring[3];            /* All VisFld's shall return strings */
  383.         int x;
  384.  
  385.         if (!(vf && s)) return s;
  386.  
  387.         switch (vf->Gadget->GadgetID) {
  388.                 case STRING_KIND :
  389.                 case TEXT_KIND :
  390.                 case TEXTFIELD_KIND :
  391.                         return s;
  392.                         break;
  393.         }
  394.         stcd_i(s, &x);                  
  395.         switch (vf->Gadget->GadgetID) {
  396.                 case CHECKBOX_KIND :
  397.                         returnstring[0]=' ';
  398.                         returnstring[1]='\0';
  399.                         if (x) returnstring[0] = 'X';
  400.                         return returnstring;
  401.                         break;
  402.  
  403.                 case CYCLE_KIND :
  404.                         returnstring[0] = '\0';
  405.                         if (vf->Gadget->Flags & GFLG_DISABLED) return returnstring;
  406.                         return vf->CEnt[x % vf->NEnt];  /* % is for safety */
  407.                         break;
  408.         }
  409. }
  410.  
  411. void WriteVisFld(struct VisFldInfo *vf, struct Window *Win, char *s)
  412. /* Only updates CheckBox and Cyclegadgets if a change has been made */
  413. {
  414.         int NewCode;
  415.         
  416.         if (!s) s = EmptyString;
  417.  
  418.         switch (vf->Gadget->GadgetID) {
  419.                 case  STRING_KIND :
  420.                         GT_SetGadgetAttrs(vf->Gadget,Win,NULL, GTST_String, s,TAG_DONE);
  421.                         break;
  422.  
  423.                 case TEXT_KIND :
  424.                         GT_SetGadgetAttrs(vf->Gadget,Win,NULL, GTTX_Text, s, TAG_DONE);
  425.                         break;
  426.  
  427.                 case TEXTFIELD_KIND :
  428.                         convertLF(s);
  429.                         SetGadgetAttrs(vf->Gadget,Win,NULL, TEXTFIELD_Text, s, TAG_DONE); /* NOT GT_ */
  430.                         convertLF(s);
  431.                         break;
  432.  
  433.                 default :
  434.                         stcd_i(s, &NewCode);
  435.                         if (NewCode != vf->Code) {
  436.                                 vf->Code = NewCode;
  437.                                 switch (vf->Gadget->GadgetID) {
  438.                                         case CHECKBOX_KIND :
  439.                                                 GT_SetGadgetAttrs(vf->Gadget,Win,NULL,
  440.                                                  GTCB_Checked, NewCode, TAG_DONE);
  441.                                                 break;
  442.                                                 
  443.                                         case CYCLE_KIND :
  444.                                                 GT_SetGadgetAttrs(vf->Gadget,Win,NULL,
  445.                                                  GTCY_Active, NewCode, TAG_DONE);
  446.                                                 break;
  447.                                 }
  448.                         }
  449.                         break;
  450.         }
  451. }
  452.  
  453. __inline char *MyStrCpy(char *dest, char *src)
  454. {
  455.         while(*dest++ = *src++);
  456.         return dest;
  457. }
  458.  
  459. __inline int QuickLen(struct Rec *crp, short offset)
  460. {
  461.         return crp->Fields[offset+1] - crp->Fields[offset] - 1;
  462. }
  463.  
  464. BOOL UpdateFld(struct Rec *crp, short offset, char *s)
  465. {
  466.         /* Return TRUE if some change has been made */
  467.         Field *nl, *ol = crp->Fields;
  468.         Field next, oldfld, olddata = NULL;
  469.         int i, len, diff, size, oldsize = 0;
  470.  
  471.         /* Is an update necessary? */
  472.         if (!strcmp(s, GetFld(crp, offset))) return FALSE;
  473.  
  474.         /* Ok, lets do the tedious update now */
  475.         len = strlen(s);
  476.         if (ol) {
  477.                 olddata = ol[0];
  478.                 oldsize = ol[crp->FldSum]-ol[0];
  479.         }
  480.         diff = offset - (crp->FldSum-1);
  481.  
  482.         if (diff > 0) {                                 /* expand list. i.e. create a new one */
  483.                 size = oldsize + diff + len;    /* (diff-1) + (len+1) */
  484.                 if (!(nl = AllocMem((2+offset)*sizeof(Field), 0))) return FALSE;
  485.                 if (!(nl[0] = AllocMem(size, 0))) {
  486.                         FreeMem(nl, (2+offset)*sizeof(Field));
  487.                         return FALSE;
  488.                 }
  489.                 /* Copy data */
  490.                 for (i=0; i < crp->FldSum; i++) {
  491.                         nl[i+1] = MyStrCpy(nl[i], ol[i]);       /* MyStrCpy returns address after end of dest. */
  492.                 }
  493.                 for (; i < offset; i++) {
  494.                         nl[i+1] = MyStrCpy(nl[i], EmptyString);
  495.                 }
  496.                 nl[i+1] = MyStrCpy(nl[i], s);
  497.  
  498.                 /* Clean up */
  499.                 if (ol) FreeMem(ol, (1+crp->FldSum)*sizeof(Field));
  500.                 crp->Fields = nl;
  501.                 crp->FldSum = offset+1;
  502.         }
  503.         else {  /* Reuse old list (there is always an old list here) */
  504.                 size = oldsize - (ol[offset+1]-ol[offset]) + len+1;
  505.  
  506.                 if (!(ol[0] = AllocMem(size, 0))) { ol[0] = olddata; return FALSE; }
  507.  
  508.                 /* Copy data */
  509.                 for (i=0, oldfld = olddata; i < crp->FldSum; i++) {
  510.                         if (i == offset) next = MyStrCpy(ol[i], s);
  511.                         else next = MyStrCpy(ol[i], oldfld);
  512.                         oldfld = ol[i+1];
  513.                         ol[i+1] = next;
  514.                 }
  515.         }
  516.         if (olddata) FreeMem(olddata, oldsize);                 /* Clean up */
  517.         return TRUE;
  518. }
  519.  
  520.  
  521. void UpdateRecord(struct Pro *Pr)
  522. {
  523.         BOOL mod = FALSE;
  524.         struct Rec *crp = *Pr->Recpp;
  525.         struct VisFldInfo *vf = Pr->CurrentLayout->FirstVisFldInfo;
  526.         char *s;
  527.  
  528.         if (Pr->Quiet || !(Pr->Modified & RECMODIFIED)) return;
  529.  
  530.         for (; vf; vf = vf->Next) {
  531.                 s = ReadVisFld(Pr, vf);
  532.                 if (UpdateFld(crp, vf->Offset, s)) mod = TRUE;
  533.         }
  534.         Pr->Modified &= ~RECMODIFIED;
  535.         if (mod && (Pr->CurrentRec == crp)) Pr->Modified |= PROMODIFIED;
  536. }
  537.  
  538.  
  539. void UpdateTitleBar(struct Pro *Pr, char *InfoTxt)
  540. {
  541.         if (Pr->Quiet) return;
  542.         if (InfoTxt) {
  543.                 sprintf(Pr->CurrentLayout->Title,"%s", InfoTxt);
  544.         }
  545.         else {
  546.                 if      (Pr->Modified & PROMODIFIED) {  /* File modified */  
  547.                         sprintf(Pr->CurrentLayout->Title,"* %s/%s %5d/%d",
  548.                          Pr->Name,Pr->CurrentLayout->Name,Pr->RecNum+1,Pr->RecSum);
  549.                 } else {
  550.                         sprintf(Pr->CurrentLayout->Title,"  %s/%s %5d/%d",
  551.                          Pr->Name,Pr->CurrentLayout->Name,Pr->RecNum+1,Pr->RecSum);
  552.                 }
  553.         }
  554.         SetWindowTitles(Pr->CurrentLayout->Window,Pr->CurrentLayout->Title,(UBYTE *)-1);
  555. }
  556.  
  557.  
  558. void UpdateDragBar(struct Pro *Pr)
  559. {
  560.         if (Pr->Quiet) return;
  561.         GT_SetGadgetAttrs(Pr->CurrentLayout->DragGad,Pr->CurrentLayout->Window, NULL,
  562.          GTSC_Total, Pr->RecSum+1,
  563.          GTSC_Top, Pr->RecNum, TAG_DONE);
  564. }
  565.  
  566. void MyActivateGadget(struct VisFldInfo *vf, struct Window *Win)
  567.         /* Gets called when user hits a field's corresponding key */
  568.         /* Stringgadgets gets activated, checkbox gadgets gets toggled and */
  569.         /* cyclegadgets gets cycled */
  570. {
  571.         VisFldSelected(vf->Gadget);
  572.  
  573.         switch (vf->Gadget->GadgetID) {
  574.                 case STRING_KIND :
  575.                 case TEXTFIELD_KIND :
  576.                         ActivateGadget(vf->Gadget, Win, NULL);
  577.                         break;
  578.  
  579.                 case CHECKBOX_KIND :
  580.                         vf->Code = (vf->Code) ? 0 : 1;
  581.                         GT_SetGadgetAttrs(vf->Gadget,Win,NULL,
  582.                          GTCB_Checked, vf->Code, TAG_DONE);
  583.                         break;
  584.                         
  585.                 case CYCLE_KIND :
  586.                         if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) /* Cycle backwards */
  587.                                 vf->Code = (vf->Code+vf->NEnt-1) % vf->NEnt;
  588.                         else vf->Code = (vf->Code+1) % vf->NEnt;
  589.  
  590.                         GT_SetGadgetAttrs(vf->Gadget,Win,NULL,
  591.                          GTCY_Active, vf->Code, TAG_DONE);
  592.                         break;
  593.         }
  594. }
  595.  
  596. void UpdateGadgets(struct Pro *Pr)
  597. {
  598.         UWORD pos;
  599.         struct Rec *crp = *Pr->Recpp;
  600.         struct VisFldInfo *vf = Pr->CurrentLayout->FirstVisFldInfo;
  601.  
  602.         if (Pr->Quiet) return;
  603.         if (!vf) return;
  604.         if (Pr->CurrentLayout->ComplexGadgets) {        /* CheckBox and Cyclegadgets */
  605.                 for (; vf; vf = vf->Next)
  606.                         WriteVisFld(vf, Pr->CurrentLayout->Window, GetFld(crp,vf->Offset));
  607.         }
  608.         else {  /* Just Stringadgets in current view. This one is faster. */
  609.                 pos = RemoveGList(Pr->CurrentLayout->Window, Pr->CurrentLayout->FirstVisFldInfo->Gadget, -1);
  610.                 /* Do the update here */
  611.  
  612.                 for (; vf; vf = vf->Next) 
  613.                                 strcpy(GetStr(vf->Gadget), GetFld(crp, vf->Offset));
  614.  
  615.                 /* Re link */
  616.                 AddGList(Pr->CurrentLayout->Window, Pr->CurrentLayout->FirstVisFldInfo->Gadget, pos, -1, NULL);
  617.                 RefreshGList(Pr->CurrentLayout->FirstVisFldInfo->Gadget, Pr->CurrentLayout->Window, NULL, -1);
  618.         }
  619.  
  620.         if (MyRexxPort && (Pr->Mode == MODE_NORMAL)) {  /* Run rexx scripts when a new record appears */
  621.                 struct RFFTag *rxtag;
  622.                 BOOL success = FALSE;
  623.  
  624.                 if (rxtag = SearchTags(CurrentPro, NULL, NULL, NEWRECORDRXFILE, NEWRECORDRXSTRING))
  625.                         if (rxtag->ID == NEWRECORDRXSTRING) success = SendRexxStrCommand(rxtag->Data);
  626.                         else success = SendRexxCommand(rxtag->Data);
  627.  
  628.                 if (success) {
  629.                         do WaitPort(MyRexxPort);
  630.                         while (!HandleRexxMessage(MyRexxPort));
  631.                 }
  632.         }
  633. }
  634.  
  635. void UpdateWindow(struct Pro *Pr)
  636. {
  637.         UpdateTitleBar(Pr,NULL);
  638.         UpdateGadgets(Pr);
  639. }
  640.  
  641. BOOL CopyToClipboard(struct Pro *Pr)
  642. {
  643.         Field fld;
  644.         struct Rec *crp = *Pr->Recpp;
  645.         struct VisFldInfo *vf = Pr->CurrentLayout->FirstVisFldInfo;
  646.         struct FldInfo *f = Pr->FirstFldInfo;
  647.         int i, len;
  648.         char normalsep[]="X", parasep[] = "\n\n", *separator = NULL;
  649.         char *s;
  650.         
  651.         if (OpenIFF(Iff0, IFFF_WRITE)) return FALSE;
  652.         if (PushChunk(Iff0, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) {
  653.                 CloseIFF(Iff0);
  654.                 return FALSE;
  655.         }
  656.         if (PushChunk(Iff0, 0, ID_CHRS, IFFSIZE_UNKNOWN)) {
  657.                 CloseIFF(Iff0);
  658.                 return FALSE;
  659.         }
  660.  
  661.         for (; vf; vf = vf->Next) {
  662.                 if (separator) {
  663.                         if (strlen(separator) != WriteChunkBytes(
  664.                          Iff0,separator,strlen(separator))) {
  665.                                 CloseIFF(Iff0);
  666.                                 return FALSE;
  667.                         }
  668.                 }
  669.                 if (*(fld = GetFld(crp,vf->Offset))) {
  670.                         s = CodeToText(vf, fld);
  671.                         len = strlen(s);
  672.                         if (len != WriteChunkBytes(Iff0,s,len)) {
  673.                                 CloseIFF(Iff0);
  674.                                 return FALSE;
  675.                         }
  676.                 }
  677.                 if ((normalsep[0] = vf->VisSep) == '\f') separator = parasep;
  678.                 else separator = normalsep;
  679.         }
  680.  
  681.         if (!PopChunk(Iff0)) PopChunk(Iff0);
  682.         CloseIFF(Iff0);
  683.  
  684.         /* Now do unit 1 */     
  685.         if (OpenIFF(Iff1, IFFF_WRITE)) return FALSE;
  686.         if (PushChunk(Iff1, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) {
  687.                 CloseIFF(Iff1);
  688.                 return FALSE;
  689.         }
  690.         if (PushChunk(Iff1, 0, ID_CHRS, IFFSIZE_UNKNOWN)) {
  691.                 CloseIFF(Iff1);
  692.                 return FALSE;
  693.         }
  694.  
  695.         for (i=0; f; f = f->Next,i++) {
  696.                 if (*(fld = GetFld(crp,i))) {
  697.                         len = strlen(f->Name);
  698.                         if (len != WriteChunkBytes(Iff1,f->Name,len)) {
  699.                                 CloseIFF(Iff1);
  700.                                 return FALSE;
  701.                         }
  702.                         if (1 != WriteChunkBytes(Iff1,"\t",1)) {
  703.                                 CloseIFF(Iff1);
  704.                                 return FALSE;
  705.                         }
  706.                         len = strlen(fld);
  707.                         if (len != WriteChunkBytes(Iff1,fld,len)) {
  708.                                 CloseIFF(Iff1);
  709.                                 return FALSE;
  710.                         }
  711.                         if (1 != WriteChunkBytes(Iff1,"\n",1)) {
  712.                                 CloseIFF(Iff1);
  713.                                 return FALSE;
  714.                         }       
  715.                 }
  716.         }
  717.  
  718.         if (!PopChunk(Iff1)) PopChunk(Iff1);
  719.         CloseIFF(Iff1);
  720.  
  721.         return TRUE;
  722. }
  723.  
  724. BOOL ClipToRec(struct Pro *Pr, struct Rec *crp, char *clipbuf)
  725. {
  726.         struct FldInfo *f;
  727.         short offset;
  728.         char *p;
  729.         BOOL retval = FALSE, found;
  730.  
  731.         while (*clipbuf) {
  732.                 found = FALSE;
  733.                 if (!(p = strpbrk(clipbuf,"\t"))) break;
  734.                 *p = '\0';
  735.                 for (offset = 0,f = Pr->FirstFldInfo; f; offset++, f = f->Next) {
  736.                         if (!(Stricmp(f->Name,clipbuf))) {
  737.                                 found = TRUE;
  738.                                 clipbuf = p+1;                          /* Move to data */
  739.                                 if (!(p = strpbrk(clipbuf,"\n"))) return FALSE;
  740.                                 *p = '\0';
  741.                                 UpdateFld(crp, offset, clipbuf);
  742.                                 retval = TRUE;
  743.                         }
  744.                 }
  745.                 clipbuf = p+1;
  746.                 if (!found) {   /* Skip unknown data */
  747.                         if (!(p = strpbrk(clipbuf,"\n"))) return FALSE;
  748.                         clipbuf = p+1;
  749.                 }
  750.         }
  751.         return retval;
  752. }
  753.  
  754.  
  755. BOOL PasteFromClipboard(struct Pro *Pr, struct Rec *crp)
  756. {
  757.         struct ContextNode *cn;
  758.         UBYTE *buf;
  759.         BOOL retval = FALSE;
  760.         long error, rlen;
  761.         if (!(buf = AllocMem(LOADBUFFERSIZE*10,0))) return FALSE;
  762.  
  763. /*      if (Iff1 = AllocIFF()) {
  764.                 if (Iff1->IFF_Stream = (ULONG) OpenClipboard(1)) {
  765.                         InitIFFasClip(Iff1); */
  766.                         if (!OpenIFF(Iff1, IFFF_READ)) {
  767.                                 /* Stop on CHRS chunks */
  768.                                 if (!StopChunk(Iff1, ID_FTXT, ID_CHRS)) {
  769.                                         /* Find all FTXT CHRS chunks */
  770.                                         while (1) {
  771.                                                 error = ParseIFF(Iff1, IFFPARSE_SCAN);
  772.                                                 if (error == IFFERR_EOC) continue;      /* End of context */
  773.                                                 else if (error) break;
  774.                                                 cn = CurrentChunk(Iff1);
  775.                                         
  776.                                                 if((cn)&&(cn->cn_Type == ID_FTXT)&&(cn->cn_ID == ID_CHRS)) {
  777.                                                         while((rlen = ReadChunkBytes(Iff1,buf,LOADBUFFERSIZE-1)) > 0) {
  778.                                                                 buf[rlen] = (UBYTE)'\0';        /* ReadChunkBytes won't do this */
  779.                                                                 retval = ClipToRec(Pr,crp, buf);
  780.                                                         }
  781.                                                         if(rlen < 0) error = rlen;
  782.                                                 }
  783.                                         } /* while */
  784.                                         if((error)&&(error != IFFERR_EOF)) retval = FALSE;
  785.                                 } /* StopChunk */
  786.                                 CloseIFF(Iff1);
  787.                         } /* OpenIFF */
  788. /*                      CloseClipboard((struct ClipboardHandle *)Iff1->IFF_Stream);
  789.                 } /* OpenClipboard */
  790.                 FreeIFF(Iff1);
  791.         } /* AllocIFF */
  792. */      FreeMem(buf,LOADBUFFERSIZE*10);
  793.         return retval;
  794. }
  795.  
  796. void DisableComplex(struct Layout *Lay, BOOL disable)
  797. /* Disables/enables complex gadgets, ie checkbox and cyclegadgets in a view */
  798. {
  799.         struct VisFldInfo *vf = Lay->FirstVisFldInfo;
  800.         for (; vf; vf = vf->Next) {
  801.                 if ((vf->Gadget->GadgetID == CHECKBOX_KIND) ||
  802.                          (vf->Gadget->GadgetID == CYCLE_KIND))
  803.                         GT_SetGadgetAttrs(vf->Gadget,Lay->Window,NULL,
  804.                          GA_Disabled, disable, TAG_DONE);
  805.         }
  806. }
  807.  
  808. void SetProMode(struct Pro *Pr, char Mode)
  809. /* Sets the mode and corrects the menus and gadgets */
  810. /* Old data in gadgets has to be saved prior to calling this function */
  811. {
  812. //      if (Pr->Mode == Mode) return;           /* Already this mode */
  813.         if (!(Pr->CurrentLayout && Pr->CurrentLayout->Window)) return;
  814.  
  815.         if (!Pr->Quiet) UpdateRecord(Pr);       
  816.         Pr->Mode = Mode;
  817.  
  818.         switch (Mode) { /* New mode */
  819.         case MODE_NORMAL:
  820.                 Pr->Recpp = &Pr->CurrentRec;
  821.                 if (Pr->Quiet) break;
  822.                 OnMenu(Pr->CurrentLayout->Window, FULLMENUNUM(0,NOITEM,NOSUB)); /* Project */
  823.                 OnMenu(Pr->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Add */
  824.                 OnMenu(Pr->CurrentLayout->Window, FULLMENUNUM(3,5,NOSUB)); /* Action->Browse */
  825.                 OnMenu(Pr->CurrentLayout->Window, FULLMENUNUM(2,NOITEM,NOSUB)); /* Action */
  826.  
  827.                 DisableComplex(Pr->CurrentLayout, FALSE);
  828.                 UpdateWindow(Pr);
  829.                 UpdateDragBar(Pr);
  830.                 break;
  831.         case MODE_FIND:
  832.                 Pr->Recpp = &Pr->FindRec;
  833.                 if (Pr->Quiet) break;
  834.                 OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(0,NOITEM,NOSUB)); /* Project */
  835.                 OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Add */
  836.                 OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(3,5,NOSUB)); /* Action->Browse */
  837.                 OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(2,NOITEM,NOSUB)); /* Action */
  838.  
  839.                 UpdateTitleBar(Pr, GetAppStr(MSG_FIND_MODE_WINMSG));
  840.                 GT_SetGadgetAttrs(Pr->CurrentLayout->DragGad,
  841.                  Pr->CurrentLayout->Window, NULL,
  842.                  GTSC_Total, 2,
  843.                  GTSC_Top, 0, TAG_DONE);
  844.  
  845.                 DisableComplex(Pr->CurrentLayout, TRUE);
  846.                 UpdateGadgets(Pr);
  847.                 break;
  848.  
  849.         case MODE_SORT:
  850.                 Pr->Recpp = &Pr->SortRec;
  851.                 if (Pr->Quiet) break;
  852.                 OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(0,NOITEM,NOSUB)); /* Project */
  853.                 OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Add */
  854.                 OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(3,5,NOSUB)); /* Action->Browse */
  855.                 OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(2,NOITEM,NOSUB)); /* Action */
  856.  
  857.                 UpdateTitleBar(Pr, GetAppStr(MSG_SORT_MODE_WINMSG));
  858.  
  859.                 GT_SetGadgetAttrs(Pr->CurrentLayout->DragGad,
  860.                  Pr->CurrentLayout->Window, NULL,
  861.                  GTSC_Total, 2,
  862.                  GTSC_Top, 0, TAG_DONE);
  863.                 DisableComplex(Pr->CurrentLayout, TRUE);
  864.                 UpdateGadgets(Pr);
  865.                 break;
  866.         }
  867. /**/    if (ReactivateGad)
  868.                  ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  869.  
  870. }
  871.  
  872.  
  873. __inline void ClearRecord(struct Rec *crp)
  874. {
  875.         if (!crp->Fields) return;
  876.         FreeMem(crp->Fields[0], crp->Fields[crp->FldSum] - crp->Fields[0]);
  877.         FreeMem(crp->Fields, (1+crp->FldSum)*sizeof(Field));
  878.         crp->Fields = NULL;
  879.         crp->FldSum = 0;
  880. }
  881.  
  882. struct Rec *NewRecord(void)
  883. {
  884.         struct Rec *rp;
  885.         if (!(rp = (struct Rec *) AllocMem(sizeof(struct Rec),0))) return NULL;
  886.         /* Initialize the data */
  887.         rp->Prev = rp->Next = NULL;
  888.         rp->Fields = NULL;
  889.         rp->FldSum = 0;
  890. }
  891.  
  892. struct Rec *AddRecord(struct Rec **crpp) /* Pointer to pointer to curr rec */
  893. {
  894.         /* Unfortunately this function also creates a record */
  895.         struct Rec *rp = NewRecord();
  896.  
  897.         if (!rp) return NULL;
  898.         
  899.         if (*crpp) {
  900.                 rp->Next = (*crpp)->Next;                               /* Curr  New->Next */
  901.                 (*crpp)->Next = rp;                                             /* Curr->New  Next */
  902.                 rp->Prev = *crpp;                                                       /* Curr<-New  Next */
  903.                 if (rp->Next) rp->Next->Prev = rp;      /* Curr  New<-Next */
  904.         }
  905.         else { /* First record */
  906.                 rp->Next = NULL;
  907.                 rp->Prev = NULL;
  908.                 *crpp = rp;
  909.         }
  910.         return rp;
  911. }
  912.  
  913.  
  914. void DeleteRecord(struct Rec **crpp)
  915. {
  916.         struct Rec *rp = *crpp;
  917.  
  918.         ClearRecord(*crpp);
  919.  
  920.         if (rp->Next) *crpp = rp->Next;                 /* Prev  Curr >Next */
  921.          else if (rp->Prev) *crpp = rp->Prev;   /* Prev< Curr  Next */
  922.           else *crpp = NULL;                                                    /* Empty list */
  923.  
  924.         /* unlink it */
  925.         if (rp->Prev)   rp->Prev->Next = rp->Next;                      /* Prev   ->   Next */
  926.         if (rp->Next) rp->Next->Prev = rp->Prev;                        /* Prev   <-   Next */
  927.         FreeMem(rp,sizeof(struct Rec));
  928.  
  929. }
  930.  
  931. BOOL KillRecord(struct Pro *Pr)
  932. /* Does some checking, handles RecNum and RecSum and calls DeleteRecord */
  933. {
  934.         if (Pr->RecSum > 1) {
  935.                 Pr->RecSum--;
  936.                 if (Pr->RecNum >= Pr->RecSum)
  937.                         Pr->RecNum--;
  938.                 DeleteRecord(&Pr->CurrentRec);
  939.                 return TRUE;
  940.         }
  941.         return FALSE;
  942. }
  943.  
  944. BOOL Match(struct Rec *Rec, struct Rec *T, struct Rec *TokenRec)
  945. {
  946.         short  offset;
  947.         Field fld, tfld, tokf;
  948.  
  949.         for (offset = 0; offset < T->FldSum; offset++) {
  950.                 if (*(tfld = GetFld(T, offset))) {                                       /* There is a pattern */
  951.                         fld = GetFld(Rec,offset);
  952.                         if (*(tokf = GetFld(TokenRec, offset))) {                /* Check if AmigaDOS match */
  953.                                 if (!MatchPatternNoCase(tokf, fld)) return FALSE;
  954.                         }
  955.                         else if (Strnicmp(fld, tfld, QuickLen(T, offset))) return FALSE;
  956.                 }
  957.         }
  958.         return TRUE;
  959. }
  960.  
  961. struct Rec *BuildTokenRec(struct Rec *FindRec)
  962. {
  963.         struct Rec *tokenrec = NewRecord();
  964.         Field f, tmp;
  965.         short offset, tmpsize;
  966.  
  967.         if (!tokenrec) return NULL;
  968.         for (offset = FindRec->FldSum-1; offset >= 0; offset--) {       /* efficient UpdateFld */
  969.                 if (*(f = GetFld(FindRec, offset))) {
  970.                         tmpsize = strlen(f)*2+10;               /* Enough according to autodocs */
  971.                         if (!(tmp = AllocMem(tmpsize, 0))) break;
  972.                         if (ParsePatternNoCase(f, tmp, tmpsize))        /* WildCards exist */
  973.                                 UpdateFld(tokenrec, offset, tmp);
  974.                         FreeMem(tmp, tmpsize);
  975.                 }
  976.         }
  977.         return tokenrec;
  978. }               
  979.  
  980. struct Rec *FindRecord(struct Pro *Pr, int StartRec, int Dir)
  981. {
  982.         int TmpRecNum;
  983.         struct Rec *TmpCurrentRec, *tokenrec;
  984.         
  985.         if (StartRec >= Pr->RecSum) { /* Out of bounds */
  986.                 if (!Pr->Quiet) DisplayBeep(Scr);
  987.                 return NULL;
  988.         }
  989.  
  990.         TmpRecNum = Pr->RecNum;
  991.         TmpCurrentRec = Pr->CurrentRec;
  992.         
  993.         UpdateRecord(Pr);
  994.  
  995.         /* Build a tokenrec for MatchPatternNoCase() */
  996.         if (!(tokenrec = BuildTokenRec(Pr->FindRec))) return NULL;
  997.  
  998.         JumpList(Pr,-Pr->RecNum+StartRec);
  999.  
  1000.         do {
  1001.                 if (Match(Pr->CurrentRec,Pr->FindRec,tokenrec)) {
  1002.                         DeleteRecord(&tokenrec);
  1003.                         SetProMode(Pr,MODE_NORMAL);
  1004.                         return Pr->CurrentRec;
  1005.                 }
  1006.         } while (JumpList(Pr,Dir));
  1007.          
  1008.         /* No match */
  1009.         /* First free the tokenrec */
  1010.         DeleteRecord(&tokenrec);
  1011.         
  1012.         if (!Pr->Quiet) DisplayBeep(Scr);
  1013.         Pr->RecNum = TmpRecNum;
  1014.         Pr->CurrentRec = TmpCurrentRec;
  1015.         return NULL;
  1016. }
  1017.  
  1018.  
  1019. BOOL LoadRecord(BPTR fp, char *buf, struct Pro *Pr, struct Rec *crp)
  1020. {
  1021.         /* The contents in this function takes more than 7/8 of the loading time to execute */
  1022.         /* Conclusion: Load the whole database in one chunk using AmigaDOS functions! */
  1023.  
  1024.         int i = 0;       /* d */
  1025.         register char *bp = buf;
  1026.  
  1027.         if (!FGets(fp, buf, LOADBUFFERSIZE-1)) return FALSE;    /* -1 is a v36 safety */
  1028.         for (bp = buf; *bp; bp++) if (*bp == '\t') crp->FldSum++;
  1029.  
  1030.         if (bp > buf && bp[-1] == '\n') *--bp = '\0';
  1031.         if (bp == buf) return TRUE;
  1032.         crp->FldSum++;
  1033.  
  1034. /* From here to the end of this function takes 1/8 of the loading time */
  1035.  
  1036.         if (!(crp->Fields = AllocMem((crp->FldSum+1)*sizeof(Field), 0))) return FALSE;
  1037.         if (!(crp->Fields[0] = AllocMem(bp-buf+1, 0))) {
  1038.                 FreeMem(crp->Fields, (crp->FldSum+1)*sizeof(Field));
  1039.                 crp->Fields = NULL;
  1040.                 return FALSE;
  1041.         }
  1042.         for (bp = crp->Fields[0]; *bp = *buf; bp++, buf++) {
  1043.                 if (*bp == '\t') {
  1044.                         *bp = '\0';
  1045.                         crp->Fields[++i] = bp+1;
  1046.                 }
  1047.         }
  1048.         crp->Fields[++i] = bp+1;
  1049.  
  1050.         return TRUE;
  1051. }
  1052.  
  1053.  
  1054. BOOL Save1stLine(struct Pro *Pr, BPTR fp, char SaveMode)
  1055. {
  1056.         struct FldInfo *f;
  1057.         char separator = '\0';
  1058.  
  1059.         for (f = Pr->FirstFldInfo; f; f=f->Next) {
  1060.                 if(!separator) {
  1061.                         if (SaveMode == SAVE_COMMA_ASCII) separator = ',';
  1062.                         else separator = '\t';
  1063.                 }
  1064.                 else if (FPutC(fp, separator) == EOF) return FALSE;
  1065.                 if (SaveMode == SAVE_COMMA_ASCII) if (FPutC(fp, '\"') == EOF) return FALSE;
  1066.                 if (FPuts(fp, f->Name) == EOF) return FALSE;
  1067.                 if (SaveMode == SAVE_COMMA_ASCII) if (FPutC(fp, '\"') == EOF) return FALSE;
  1068.         }
  1069.         if (FPutC(fp, '\n') == EOF) return FALSE;
  1070.         return TRUE;                    
  1071. }
  1072.  
  1073.  
  1074. BOOL SaveRecord(struct Rec *crp, BPTR fp, char SaveMode)
  1075. {
  1076.         Field fld;
  1077.         int nsepa = 0;
  1078.         int i;
  1079.         BOOL empty = TRUE;
  1080.  
  1081.         if (SaveMode == SAVE_COMMA_ASCII) {
  1082.                 for (i = 0; i < crp->FldSum; i++) {
  1083.                         if (*(fld = GetFld(crp, i))) {
  1084.                                 empty = FALSE;
  1085.                                 while (nsepa--) if (FPutC(fp, ',') == EOF) return FALSE;
  1086.                                 if (FPutC(fp, '\"') == EOF) return FALSE;
  1087.                                 if (FPuts(fp, fld) == EOF) return FALSE;
  1088.                                 if (FPutC(fp, '\"') == EOF) return FALSE;
  1089.                                 nsepa = 0;
  1090.                         }
  1091.                         nsepa++;
  1092.                 }
  1093.         }
  1094.         else {
  1095.                 for (i = 0; i < crp->FldSum; i++) {
  1096.                         if (*(fld = GetFld(crp, i))) {
  1097.                                 empty = FALSE;
  1098.                                 while (nsepa--) if (FPutC(fp, '\t') == EOF) return FALSE;
  1099.                                 if (FPuts(fp, fld) == EOF) return FALSE;
  1100.                                 nsepa = 0;
  1101.                         }
  1102.                         nsepa++;
  1103.                 }
  1104.         }
  1105.         if (!empty && FPutC(fp, '\n') == EOF) return FALSE;
  1106.         return TRUE;
  1107. }
  1108.  
  1109.  
  1110. BOOL SaveView(struct Pro *Pr, struct Rec *crp, BPTR fp, BOOL names)
  1111. {
  1112.         char buffer[FIELDNAMELENGTH];
  1113.         char *bufp, *namep, *s;
  1114.  
  1115.         Field fld;
  1116.         struct VisFldInfo *vf = Pr->CurrentLayout->FirstVisFldInfo;
  1117.  
  1118.         for (; vf; vf = vf->Next) {
  1119.                 if (names) {
  1120.                         /* Strip underscore _ in gadetname for correct length */
  1121.                         for (bufp = buffer, namep = vf->Name;; namep++) {
  1122.                                 if (*namep != '_') *bufp++ = *namep;
  1123.                                 if (!(*namep)) break;   /* Also copy the \0 char */
  1124.                         }
  1125.                         if (FPuts(fp, buffer) == EOF) return FALSE;
  1126.                         if (FPuts(fp, ": ") == EOF) return FALSE;
  1127.                 }
  1128.  
  1129.                 if (*(fld = GetFld(crp,vf->Offset))) {
  1130.                         s = CodeToText(vf, fld);
  1131.                         if (FPuts(fp, s) == EOF) return FALSE;
  1132.                 }
  1133.                 if (vf->VisSep == '\f') {
  1134.                         if (FPutC(fp, '\n') == EOF) return FALSE;
  1135.                         if (FPutC(fp, '\n') == EOF) return FALSE;
  1136.                 }
  1137.                 else if (FPutC(fp, vf->VisSep) == EOF) return FALSE;
  1138.         }
  1139.         return TRUE;
  1140. }
  1141.  
  1142.  
  1143. BOOL ClearPro(struct Pro *Pr)
  1144. {
  1145.         /* First delete old data */
  1146.         JumpList(Pr,Pr->RecSum-Pr->RecNum-1);                   /* Jump to last record for speed */
  1147.         while (Pr->RecSum--) DeleteRecord(&Pr->CurrentRec); 
  1148.         Pr->RecNum = 0;
  1149.         Pr->RecSum = 0; /* No risk that RecSum gets -1 */
  1150.  
  1151.         /* Add one record */
  1152.         if (!AddRecord(&Pr->CurrentRec)) return FALSE;
  1153.         Pr->RecSum++;
  1154.  
  1155.         /* We really don't use FirstRec, but we initialize it anyway */
  1156.         Pr->FirstRec = Pr->CurrentRec;
  1157.         /* This also updates the window with empty fields */
  1158.         SetProMode(Pr,MODE_NORMAL);
  1159.         return TRUE;
  1160. }
  1161.  
  1162. void DeleteLayout(struct Pro *Pr, struct Layout *Lay)
  1163. {
  1164.         struct RFFTag *ot;
  1165.         struct VisFldInfo *vf, *nextvf;
  1166.         
  1167.         if (!Lay) return; /* Safety */
  1168.  
  1169.         if (Lay->Browser) DeleteSelect(Lay->Browser);
  1170.  
  1171.         CloseLayWin(Pr, Lay);
  1172.  
  1173.         for (vf = Lay->FirstVisFldInfo; vf; vf=nextvf) {
  1174.                 nextvf = vf->Next;
  1175.                 DeleteVisFldInfo(vf);
  1176.         }
  1177.         Lay->FirstVisFldInfo = NULL;
  1178.  
  1179.         while (ot = (struct RFFTag *)RemHead((struct List *)&Lay->LayTags))
  1180.          DeleteTag(ot);
  1181.  
  1182.         FreeMem(Lay, sizeof(struct Layout));
  1183. }
  1184.  
  1185. struct Layout *NewLayout(struct Pro *Pr)
  1186. {
  1187.         struct Layout *Lay, *l;
  1188.  
  1189.         if (!(Lay = AllocMem(sizeof(struct Layout), MEMF_CLEAR))) return NULL;
  1190.         NewList((struct List *)&Lay->LayTags);
  1191.         
  1192.         strcpy(Lay->Name,Pr->Name);     /* Same name initially */
  1193.         Lay->ComplexGadgets = FALSE;    /* Faster redraw routines without checkbox */
  1194.                                                                                         /* and cyclegadgets */
  1195.  
  1196.         Lay->XPos = Lay->YPos = -1;     /* Let db think */
  1197.         
  1198.         /* Add this struct to the list */
  1199.         if (!(l = Pr->FirstLayout)) Pr->FirstLayout = Lay;
  1200.         else {
  1201.                 while (l->NextLayout) l = l->NextLayout;
  1202.                 l->NextLayout = Lay;
  1203.         }
  1204.  
  1205.         /* Browser stuff */
  1206.         Lay->Browser = NewSelect();
  1207.  
  1208.  
  1209.         Pr->CurrentLayout = Lay;
  1210.         return Lay;
  1211. }
  1212.  
  1213. void DeletePro(struct Pro *Pr)
  1214. {
  1215.         struct FldInfo *f, *old;
  1216.         struct RxInfo *ri, *oldri;
  1217.         struct RFFTag *ot;
  1218.         struct RFFLine *oline;
  1219.         struct Layout *l,*nextl;
  1220.  
  1221.         if (!Pr) return; /* Safety */
  1222.  
  1223.         /* Jumping to last record actually improves de-alloc speed a lot */
  1224.         /* as this is the reverse order that the records where allocated */
  1225.         JumpList(Pr,Pr->RecSum-Pr->RecNum-1);                   /* Jump to last record */
  1226.         while (Pr->RecSum--) DeleteRecord(&Pr->CurrentRec); 
  1227.         if (Pr->FindRec) DeleteRecord(&Pr->FindRec);
  1228.         if (Pr->SortRec) DeleteRecord(&Pr->SortRec);
  1229.  
  1230.         ri = Pr->FirstRxInfo;
  1231.         while (ri) {
  1232.                 while (ot = (struct RFFTag *)RemHead((struct List *)&ri->RxTags))
  1233.                  DeleteTag(ot);
  1234.                 oldri = ri; ri = ri->Next;
  1235.                 FreeMem(oldri, sizeof(struct RxInfo));
  1236.         }
  1237.         Pr->FirstRxInfo = NULL;
  1238.  
  1239.         f = Pr->FirstFldInfo;
  1240.         while (f) {
  1241.                 while (ot = (struct RFFTag *)RemHead((struct List *)&f->FldTags))
  1242.                  DeleteTag(ot);
  1243.                 old = f; f = f->Next;
  1244.                 FreeMem(old,sizeof(struct FldInfo));
  1245.         }
  1246.         Pr->FirstFldInfo = NULL;
  1247.  
  1248.         while (ot = (struct RFFTag *)RemHead((struct List *)&Pr->ProTags))
  1249.          DeleteTag(ot);
  1250.         while (oline = (struct RFFLine *)RemHead((struct List *)&Pr->UnknownLines))
  1251.          DeleteRFFLine(oline);
  1252.  
  1253.         for (l = Pr->FirstLayout; l;) {
  1254.                 nextl = l->NextLayout;
  1255.                 DeleteLayout(Pr, l);
  1256.                 l = nextl;
  1257.         }
  1258.         Pr->FirstLayout = NULL;
  1259.         
  1260.         CloseMenu(Pr);
  1261.  
  1262.         FreeMem(Pr, sizeof(struct Pro));
  1263. }
  1264.  
  1265. struct Pro *NewPro(void)
  1266. {
  1267.         struct Pro *Pr;
  1268.  
  1269.         if (!(Pr = AllocMem(sizeof(struct Pro), MEMF_CLEAR))) return NULL;
  1270.  
  1271.         NewList((struct List *)&Pr->ProTags);
  1272.         NewList((struct List *)&Pr->UnknownLines);
  1273.  
  1274.         strcpy(Pr->Name, GetAppStr(MSG_UNTITLED_PRO));
  1275.         Pr->Mode = MODE_NORMAL;
  1276.         Pr->Sep = '\t';
  1277.         Pr->Modified = NOTMODIFIED;
  1278.         Pr->Quiet = FALSE;
  1279.         Pr->Recpp = &Pr->CurrentRec;
  1280.  
  1281.             strcpy(Pr->Pattern,      (char *)MyArgArray[DEFPATTERN]);
  1282.             strcpy(Pr->ARexxPattern, (char *)MyArgArray[DEFREXXPATTERN]);
  1283.         
  1284.         /* Add one FindRec and SortRec */
  1285.  
  1286.         if (!AddRecord(&Pr->FindRec)) {
  1287.                 DeletePro(Pr);
  1288.                 return NULL;
  1289.         }
  1290.         if (!AddRecord(&Pr->SortRec)) {
  1291.                 DeletePro(Pr);
  1292.                 return NULL;
  1293.         }
  1294.  
  1295.         if (!ClearPro(Pr)) {    /* Just to add one default record */
  1296.                 DeletePro(Pr);
  1297.                 return NULL;
  1298.         }
  1299.         return Pr;
  1300. }
  1301.  
  1302.  
  1303. void SwapSwed(struct Rec *crp)
  1304. {
  1305. /* Correct the order of the swedish åäö characters */
  1306. /* Uses the global struct SI (SortInfo) to determine which fields to manipulate */
  1307.  
  1308.         int i;
  1309.         Field fld;
  1310.         signed char *p; /* To be explicit */
  1311.         
  1312.         for (i=0; i<SI.norders; i++) {
  1313.                 if (*(fld = GetFld(crp,SI.so[i].Offset))) {
  1314.                         for (p = fld; *p; p++) {
  1315.                                 if (*p & 0x80)
  1316.                                         switch (*p) {
  1317.                                                 case 'Å': *p = 'Ä'; break;
  1318.                                                 case 'Ä': *p = 'Å'; break;
  1319.                                                 case 'å': *p = 'ä'; break;
  1320.                                                 case 'ä': *p = 'å'; break;
  1321.                                         }
  1322.                         }
  1323.                 }
  1324.         }
  1325. }
  1326.  
  1327.  
  1328. int CompareRec(struct Rec **rpp1, struct Rec **rpp2)
  1329. {
  1330.         /* This function is used by qsort() to compare records. It returns values like */
  1331.         /* strcmp(). It uses the global struct SI (SortInfo) to determine details like */
  1332.         /* the sort order and which fields to sort on. */
  1333.  
  1334.         int i;
  1335.         Field fld1,fld2;
  1336.         LONG res;
  1337.         
  1338.         if (SI.UnSort) return *rpp1 - *rpp2;
  1339.  
  1340.         for (i=0; i<SI.norders; i++) {
  1341.                 fld1 = GetFld(*rpp1,SI.so[i].Offset);
  1342.                 fld2 = GetFld(*rpp2,SI.so[i].Offset);
  1343.  
  1344.                 res = SI.so[i].CmpFunc(fld1, fld2);
  1345.                 if (res) return (SI.SortDir) ? -res : res;
  1346.         }
  1347.         return 0;
  1348. }
  1349.  
  1350.  
  1351. int LocaleCmp(char *str1, char *str2)
  1352. {
  1353.         /* Frontend for the locale.library StrnCmp() string compare function. */
  1354.         return StrnCmp(MyLocale, str1, str2, -1, SC_COLLATE2);
  1355. }
  1356.  
  1357.  
  1358. int StringCmp(char *str1, char *str2)
  1359. {
  1360.         /* Frontend as one can't take the address of a dynamically linked function */
  1361.         return Stricmp(str1, str2);
  1362. }
  1363.  
  1364.  
  1365. int IntegerCmp(char *str1, char *str2)
  1366. {
  1367.         return atoi(str1) - atoi(str2);
  1368. }
  1369.  
  1370.  
  1371. int SortOrderCmp(struct SortOrder *sop1, struct SortOrder *sop2)
  1372. {
  1373.         return sop1->Order - sop2->Order;
  1374. }
  1375.  
  1376. CompFunc DecideCmpFunc(struct Pro *Pr, short offset)
  1377. {
  1378.         struct FldInfo *fi = GetFldInfo(Pr, offset);
  1379.         struct RFFTag *tag;
  1380.  
  1381.         if (!fi) return StringCmp;      /* Safety, should never happen */
  1382.         tag = FindTag(&fi->FldTags, FTYP);
  1383.  
  1384.         if (tag && !Stricmp(tag->Data,"integer")) return IntegerCmp;
  1385.         else if (MyLocale) return LocaleCmp;
  1386.         else return StringCmp;
  1387. }
  1388.  
  1389.  
  1390. void DoSort(struct Pro *Pr, short offset)
  1391. {
  1392.         /* If offset is non-negative, sort on it instead of using what is entered in */
  1393.         /* the visual fields. (The Browser uses it to do an AutoSort) */
  1394.  
  1395.         int i, offs, temp;
  1396.         struct Rec *trec = Pr->CurrentRec;
  1397.         struct Rec **recArray;
  1398.  
  1399.         if (Pr->RecSum < 2) return;
  1400.  
  1401.         /* Init SI */
  1402.         SI.norders = 0;
  1403.  
  1404.         if (offset >= 0) {
  1405.                 SI.norders = 1;
  1406.                 if (!(SI.so = AllocMem(sizeof(struct SortOrder),0))) {
  1407.                         SetProMode(Pr,MODE_NORMAL);
  1408.                         return; /* Out of memory */
  1409.                 }
  1410.                 SI.so->Order = 1; /* Safety */
  1411.                 SI.so->Offset = offset;
  1412.                 SI.so->CmpFunc = DecideCmpFunc(Pr, offset);
  1413.         }
  1414.         else if (offset == NORMAL_SORT) {
  1415.                 /* First check how many valid "orderfields" there are */
  1416.                 UpdateRecord(Pr);
  1417.  
  1418.                 for (offs=0; offs < Pr->SortRec->FldSum; offs++) {
  1419.                         if (stcd_i(GetFld(Pr->SortRec, offs), &temp)) SI.norders++;
  1420.                 }
  1421.                 if (SI.norders) {
  1422.                         if (!(SI.so = AllocMem(SI.norders * sizeof(struct SortOrder),0))) {
  1423.                                 SetProMode(Pr,MODE_NORMAL);
  1424.                                 return; /* Out of memory */
  1425.                         }
  1426.                         for (offs=i=0; offs < Pr->SortRec->FldSum; offs++) {
  1427.                                 if (stcd_i(GetFld(Pr->SortRec, offs), &temp)) {
  1428.                                         SI.so[i].Order = temp;
  1429.                                         SI.so[i].Offset = offs;
  1430.                                         SI.so[i++].CmpFunc = DecideCmpFunc(Pr, offs);
  1431.                                 }
  1432.                         }
  1433.                         qsort(SI.so, SI.norders, sizeof(struct SortOrder), SortOrderCmp);
  1434.                 }
  1435.                 else {
  1436.                         SI.UnSort = TRUE; /* Perform an UNSORT */
  1437.                         UpdateRecord(Pr);
  1438.                 }
  1439.         }
  1440.         else SI.UnSort = TRUE;  /* Perform an UNSORT */
  1441.         
  1442.         /* Prepare an array of pointers to all records for qsort() */
  1443.         if (!(recArray = AllocMem (Pr->RecSum * sizeof(struct Rec *), 0))) {
  1444.                 SetProMode(Pr, MODE_NORMAL);
  1445.                 FreeMem(SI.so, SI.norders * sizeof(struct SortOrder));
  1446.                 return;
  1447.         }
  1448.         while (trec->Prev) trec = trec->Prev; /* find start */
  1449.         if (MyLocale) for (i=0; trec; trec = trec->Next, i++) recArray[i] = trec;
  1450.         else for (i=0; trec; trec = trec->Next, i++) {
  1451.                         recArray[i] = trec;
  1452.                         SwapSwed(trec);
  1453.         }
  1454.  
  1455.         UpdateTitleBar(Pr,GetAppStr(MSG_SORTING_WINMSG)); /* Sorting might take some time */
  1456.         BlockInput(Pr->CurrentLayout->Window,FALSE);
  1457.  
  1458.         /****  qsort() ****/
  1459.         qsort(recArray, Pr->RecSum, sizeof(struct Rec *), CompareRec);
  1460.  
  1461.         if (SI.UnSort) {
  1462.                 Pr->IsSorted = FALSE;
  1463.                 SI.UnSort = FALSE;
  1464.         }
  1465.         else Pr->IsSorted = TRUE;
  1466.  
  1467.         Pr->CurrentRec = recArray[0];
  1468.         Pr->RecNum=0;
  1469.  
  1470.         /* Repair the doubly linked list now */
  1471.         recArray[0]->Prev = NULL;
  1472.         for (i=0; i < Pr->RecSum-1; i++) {
  1473.                 recArray[i]->Next = recArray[i+1];
  1474.                 recArray[i+1]->Prev = recArray[i];
  1475.         }
  1476.         recArray[i]->Next = NULL;       /* List repaired */
  1477.  
  1478.         if (!MyLocale) for (trec = Pr->CurrentRec; trec; trec = trec->Next) SwapSwed(trec);
  1479.         
  1480.         FreeMem(recArray, Pr->RecSum * sizeof(struct Rec *));
  1481.         if (SI.norders) FreeMem(SI.so, SI.norders * sizeof(struct SortOrder));
  1482.  
  1483.         FreeInput(Pr->CurrentLayout->Window);
  1484.         SetProMode(Pr,MODE_NORMAL);
  1485. }
  1486.  
  1487.  
  1488.  
  1489. BOOL IsPhoneNumber(char *nr)
  1490. {
  1491.         /* Checks if nr contains at least one number */
  1492.         BOOL ret = FALSE;
  1493.         if (!nr) return FALSE;
  1494.         while (*nr) if (isdigit(*nr++)) { ret = TRUE; break; }
  1495.         return ret;
  1496. }
  1497.  
  1498.  
  1499. BOOL SpeedRenderOn(struct Layout *Lay)
  1500. /* We build a linked list of SR structs */
  1501. {
  1502.         struct VisFldInfo *vf = Lay->FirstVisFldInfo;
  1503.         struct SR *tp, *old = NULL;
  1504.  
  1505.         if (MyArgArray[NOSPEEDRENDER]) return TRUE;     /* Break out */
  1506.  
  1507.         for (; vf; vf = vf->Next) {
  1508.                 /* SpeedRender only works for stringgadgets */
  1509.                 if (vf->Gadget->GadgetID != STRING_KIND) continue;
  1510.  
  1511.                 if (!(tp = AllocMem(sizeof(struct SR),0))) return FALSE;
  1512.                 tp->GadgetRender = vf->Gadget->GadgetRender;
  1513.                 vf->Gadget->GadgetRender = NULL;
  1514.                 tp->Next = NULL;
  1515.                 if (!old) {
  1516.                         old = tp;
  1517.                         Lay->FirstSR = tp;
  1518.                 }
  1519.                 else {
  1520.                         old->Next = tp;
  1521.                         old = tp;
  1522.                 }
  1523.         }
  1524.         return TRUE;
  1525. }
  1526.  
  1527. void SpeedRenderOff(struct Layout *Lay)
  1528. {
  1529.         struct VisFldInfo *vf = Lay->FirstVisFldInfo;
  1530.         struct SR *tp = Lay->FirstSR, *old;
  1531.         
  1532.         if (MyArgArray[NOSPEEDRENDER]) return;  /* Break out */
  1533.  
  1534.         for (; vf; vf = vf->Next) {
  1535.                 /* SpeedRender only works for stringgadgets */
  1536.                 if (vf->Gadget->GadgetID != STRING_KIND) continue;
  1537.  
  1538.                 vf->Gadget->GadgetRender = tp->GadgetRender;
  1539.                 old = tp; tp = tp->Next;
  1540.                 FreeMem(old,sizeof(struct SR));
  1541.         }
  1542.         Lay->FirstSR = NULL;
  1543. }
  1544.  
  1545. void CloseSerial(void)
  1546. {
  1547.         /* Serial device specifics */
  1548.         if (SerialIO) {
  1549.                 if (SerialIO->IOSer.io_Device) CloseDevice((struct IORequest *)SerialIO);
  1550.                 DeleteExtIO((struct IORequest *)SerialIO);
  1551.         }
  1552.         if (SerialMP) DeletePort(SerialMP);
  1553.  
  1554.         SerialMP = NULL;
  1555.         SerialIO = NULL;        
  1556. }
  1557.  
  1558. /**********************************************************************/
  1559. /*                              Byebye()                              */
  1560. /**********************************************************************/
  1561.  
  1562. void ByeBye(void)
  1563. {
  1564.         struct AppMessage *AppMsg;
  1565.  
  1566.         /* Serial specifics */
  1567.         CloseSerial();
  1568.  
  1569.         /* Clipboard specifics */
  1570.         if (Iff0) {
  1571.                 if (Iff0->iff_Stream)
  1572.                  CloseClipboard((struct ClipboardHandle *)Iff0->iff_Stream);
  1573.                 FreeIFF(Iff0);
  1574.         }
  1575.         if (Iff1) {
  1576.                 if (Iff1->iff_Stream)
  1577.                  CloseClipboard((struct ClipboardHandle *)Iff1->iff_Stream);
  1578.                 FreeIFF(Iff1);
  1579.         }
  1580.  
  1581.         /* Reclaim memory used by ReadArgs(). Don't access MyArgArray after this! */
  1582.         if (MyRDArgs)
  1583.                         FreeArgs(MyRDArgs);
  1584.         else
  1585.                         if(TTypes)
  1586.                                 ArgArrayDone();
  1587.  
  1588.         if (CurrentPro->IsSorted) DoSort(CurrentPro, UNSORT);   /* Speed. Let's help FreeMem() */
  1589.         DeletePro(CurrentPro);
  1590.  
  1591.         if (UserTextFont) CloseFont(UserTextFont);
  1592.         CloseDownScreen();      /*GadToolBox*/
  1593.  
  1594.         /* Make sure there are no more outstanding AppWin messages */
  1595.         if (AWPort) {
  1596.                 while(AppMsg = (struct AppMessage *)GetMsg(AWPort))
  1597.                         ReplyMsg((struct Message *)AppMsg);
  1598.                 DeleteMsgPort(AWPort);
  1599.         }
  1600.  
  1601.         if (MyRexxPort) CloseRexxPort(MyRexxPort);
  1602.  
  1603.         if (LocaleBase) {
  1604.                 if (MyLocale) CloseLocale(MyLocale);
  1605.                 if (LocaleInfo.li_Catalog) CloseCatalog(LocaleInfo.li_Catalog);
  1606.                 CloseLibrary (LocaleBase);
  1607.         }
  1608.         if (TextFieldBase)      CloseLibrary(TextFieldBase);
  1609.         if (RexxSysBase)                CloseLibrary(RexxSysBase);
  1610.         if (DiskfontBase)               CloseLibrary(DiskfontBase);
  1611.         if (IFFParseBase)               CloseLibrary(IFFParseBase);
  1612.         if (WorkbenchBase)      CloseLibrary(WorkbenchBase);
  1613.         if (IconBase)                   CloseLibrary(IconBase);
  1614.         if (AslBase)                    CloseLibrary(AslBase);
  1615.         if (CxBase)                             CloseLibrary(CxBase);
  1616.         if (GadToolsBase)               CloseLibrary(GadToolsBase);
  1617.         if (UtilityBase)                CloseLibrary(UtilityBase);
  1618.         if (GfxBase)                    CloseLibrary((struct Library *)GfxBase);
  1619.         if (IntuitionBase)      CloseLibrary((struct Library *)IntuitionBase);
  1620.  
  1621.         exit(0);
  1622. }
  1623.  
  1624. void HandleQuit(struct Pro *Pr)
  1625. /* This routine gets called by all quit-program routines */
  1626. {
  1627.         UpdateRecord(Pr);
  1628.         if      (Pr->Modified & PROMODIFIED)  /* File modified */  
  1629.                 if      (!EasyLocRequest(Pr->CurrentLayout->Window, &ES_QuitWarn, NULL, NULL)) return;
  1630.  
  1631.         ByeBye();
  1632. }
  1633.  
  1634. BOOL PerformSave(struct Pro *Pr, BPTR fp, char SaveMode, struct Rec *tokenrec)
  1635. {
  1636.         /* Called from SavePro. Performs the actual saving */
  1637.         /* This function exists to simplify bail-out if an error occurs */
  1638.  
  1639.         struct Rec *SaveRec;
  1640.         BOOL names = (SaveMode == SAVE_VIEW_WN);
  1641.         BOOL noview = (SaveMode != SAVE_VIEW) && (SaveMode != SAVE_VIEW_WN);
  1642.  
  1643.         if (noview)
  1644.                 if(!Save1stLine(Pr, fp, SaveMode)) return FALSE;
  1645.  
  1646.         if (SaveMode == SAVE_PRO)
  1647.                 if(!RFFOut(Pr, fp)) return FALSE;
  1648.  
  1649.         /* Seek first record */
  1650.         for (SaveRec = Pr->CurrentRec; SaveRec->Prev; SaveRec = SaveRec->Prev);
  1651.  
  1652.         /* Save the records */
  1653.  
  1654.         if (tokenrec) { /* ie filtered output */
  1655.  
  1656.                 if (noview) {
  1657.                         do {
  1658.                                 if (Match(SaveRec,Pr->FindRec,tokenrec))
  1659.                                         if (!SaveRecord(SaveRec,fp,SaveMode)) return FALSE;
  1660.                         } while (SaveRec = SaveRec->Next);
  1661.                 }
  1662.                 else {
  1663.                         do {
  1664.                                 if (Match(SaveRec,Pr->FindRec,tokenrec))
  1665.                                         if (!SaveView(Pr,SaveRec,fp,names)) return FALSE;
  1666.                         } while (SaveRec = SaveRec->Next);
  1667.                 }
  1668.         }
  1669.         else {
  1670.  
  1671.                 if (noview) {
  1672.                         do {
  1673.                                 if (!SaveRecord(SaveRec,fp,SaveMode)) return FALSE;
  1674.                         } while (SaveRec = SaveRec->Next);
  1675.                 }
  1676.                 else {
  1677.                         do {
  1678.                                 if (!SaveView(Pr,SaveRec,fp,names)) return FALSE;
  1679.                         } while (SaveRec = SaveRec->Next);
  1680.                 }
  1681.         }
  1682.  
  1683.         return TRUE;
  1684. }
  1685.  
  1686. BOOL MakeBackup(char *filename)
  1687. {
  1688.         char bakname[FMSIZE];
  1689.         strcpy(bakname, filename);
  1690.         strcat(bakname, ".bak");
  1691.         DeleteFile(bakname);
  1692.         if (!Rename(filename, bakname)) return FALSE;
  1693.         return TRUE;
  1694. }
  1695.  
  1696. BOOL SavePro(struct Pro *Pr, char *Drawer, char *Name, char SaveMode, BOOL Filter)
  1697. {
  1698.         BPTR fp;
  1699.         char filename[FMSIZE];
  1700.         struct DiskObject *DO;  /* For handling icons */
  1701.         struct Rec *tokenrec = NULL;
  1702.  
  1703.         strcpy(filename,Drawer);
  1704.         if (!AddPart(filename,Name,FMSIZE-1)) { /* incorrect filename */
  1705.                 /* display error req */
  1706.                 return FALSE;
  1707.         }
  1708.  
  1709.         if (SaveMode == SAVE_PRO && MyArgArray[MAKEBACKUP]) MakeBackup(filename);
  1710.  
  1711.         /* Open file */
  1712.         if (!(fp = Open(filename, MODE_NEWFILE))) { /* open fail */
  1713.                 EasyLocRequest(Pr->CurrentLayout->Window,
  1714.                  &ES_OpenFail, NULL, filename);
  1715.                 return FALSE;
  1716.         }
  1717.         /* Set a large buffer for increased load speed */
  1718.         SetVBuf(fp, NULL, BUF_FULL, MY_FILE_BUF);
  1719.         
  1720.         if (SaveMode == SAVE_PRO) {
  1721.                 strcpy(Pr->Drawer,Drawer);
  1722.                 strcpy(Pr->Name,Name);
  1723.         }
  1724.         else {
  1725.                 strcpy(Pr->OutputName,Name);
  1726.                 strcpy(Pr->OutputDrawer,Drawer);
  1727.         }
  1728.  
  1729.         if (Filter) {
  1730.                 /* Build a tokenrec for MatchPatternNoCase() */
  1731.                 if (!(tokenrec = BuildTokenRec(Pr->FindRec))) {
  1732.                         Close(fp);
  1733.                         return FALSE;
  1734.                 }
  1735.         }
  1736.  
  1737.         UpdateTitleBar(Pr,GetAppStr(MSG_SAVING_WINMSG)); /* User feedback that file will be saved */
  1738.         BlockInput(Pr->CurrentLayout->Window,TRUE);
  1739.         UpdateRecord(Pr); /* Don't forget this! */
  1740.  
  1741.  
  1742.         if (!PerformSave(Pr,fp,SaveMode, tokenrec)) {
  1743.                 /* Save error */
  1744.                 EasyLocRequest(Pr->CurrentLayout->Window,
  1745.                  &ES_SaveError, NULL, filename);
  1746.                 Close(fp);
  1747.                 if (tokenrec) DeleteRecord(&tokenrec);
  1748.                 FreeInput(Pr->CurrentLayout->Window);
  1749.                 UpdateTitleBar(Pr,NULL); /* Maybe a new name? */
  1750.                 return FALSE;
  1751.         }
  1752.  
  1753.         if (SaveMode == SAVE_PRO) {
  1754.                 Pr->Modified = NOTMODIFIED;
  1755.  
  1756.                 if (!MyArgArray[NOICONS]) {
  1757.                         /* Everything OK, Save an icon if one doesn't exist */
  1758.                         if (DO = GetDiskObject(filename)) FreeDiskObject(DO); /* Icon found */
  1759.                         else PutDiskObject(filename,&DataIcon); /* if no icon, create one */
  1760.                 }
  1761.         }
  1762.         Close(fp);
  1763.         if (tokenrec) DeleteRecord(&tokenrec);
  1764.         FreeInput(Pr->CurrentLayout->Window);
  1765.         UpdateTitleBar(Pr,NULL); /* Maybe a new name? */
  1766.         return TRUE;
  1767. }
  1768.  
  1769. void Save(struct Pro *Pr, char SaveMode)
  1770. {
  1771.         /* Called from "Save as..", and the "Output..." submenu */
  1772.  
  1773.    struct FileRequester *fr;
  1774.         char fullname[FMSIZE];
  1775.         BOOL dosave = TRUE;
  1776.         BOOL filter = FALSE;
  1777.         int answer;
  1778.         char *title[5];
  1779.         char *name;
  1780.         char *drawer;
  1781.  
  1782.         title[0] = GetAppStr(MSG_SAVE_AS_ASLREQ_TITLE);
  1783.         title[1] = GetAppStr(MSG_OUTPUT_VIEW_ASLREQ_TITLE);
  1784.         title[2] = GetAppStr(MSG_OUTPUT_VIEW_WN_ASLREQ_TITLE);
  1785.         title[3] = GetAppStr(MSG_OUTPUT_TAB_ASCII_ASLREQ_TITLE);
  1786.         title[4] = GetAppStr(MSG_OUTPUT_COMMA_ASCII_ASLREQ_TITLE);
  1787.  
  1788.         if (SaveMode == SAVE_PRO) {
  1789.                 name = Pr->Name;
  1790.                 drawer = Pr->Drawer;
  1791.         }
  1792.         else {  /* Output menu */
  1793.                 name = Pr->OutputName;
  1794.                 drawer = Pr->OutputDrawer;
  1795.  
  1796.                 if (answer = EasyLocRequest(Pr->CurrentLayout->Window, &ES_Ask_Filtering, NULL, NULL)) {
  1797.                          if (answer == 2) filter = TRUE;
  1798.                 }
  1799.                 else return;
  1800.         }
  1801.  
  1802.         /* By supplying the dimension tags to AllocAslRequest, PD programs like */
  1803.         /* SetASLDim may modify the size to the users preference */
  1804.    fr = AllocAslRequest(ASL_FileRequest, frtags);
  1805.  
  1806.         if (AslRequestTags(fr,ASLFR_Window,Pr->CurrentLayout->Window,
  1807.          ASLFR_SleepWindow,TRUE,
  1808.          ASLFR_DoSaveMode,TRUE,
  1809.          ASLFR_TitleText,title[SaveMode],
  1810.          ASLFR_InitialDrawer, drawer,
  1811.          ASLFR_InitialFile, name,
  1812.          TAG_DONE)) {
  1813.                 strcpy(fullname,fr->fr_Drawer);
  1814.                 AddPart(fullname,fr->fr_File,FMSIZE-1);
  1815.                 if (!access(fullname, F_OK))    /* Found a file with the same name */
  1816.                         if (!EasyLocRequest(Pr->CurrentLayout->Window, &ES_SaveWarn, NULL,fr->fr_File)) dosave = FALSE;
  1817.                 if (dosave == TRUE) SavePro(Pr,fr->fr_Drawer,fr->fr_File, SaveMode, filter);
  1818.         }
  1819.         FreeAslRequest(fr);
  1820. }
  1821.  
  1822.  
  1823. struct Pro *LoadPro(char *Drawer, char *Name)
  1824. {
  1825.         struct Pro *npr;
  1826.         BPTR fp;
  1827.         char *buf;      /* This buffer holds max one field at a time */
  1828.         char fullname[FMSIZE];
  1829.         int retval;
  1830.  
  1831.         UpdateRecord(CurrentPro);
  1832.         if      (CurrentPro->Modified & PROMODIFIED)  /* File modified */  
  1833.                 if      (!EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_LoadWarn,
  1834.                  NULL, NULL)) return NULL;
  1835.                 
  1836.         strcpy(fullname,Drawer);
  1837.         if (!AddPart(fullname,Name,FMSIZE-1))   { /* incorrect filename */
  1838.                 /* display error req */
  1839.                 return NULL;
  1840.         }
  1841.         if (!(fp = Open(fullname, MODE_OLDFILE))) { /* open fail */
  1842.                 EasyLocRequest(CurrentPro->CurrentLayout->Window,
  1843.                  &ES_OpenFail, NULL, fullname);
  1844.                 return NULL;
  1845.         }
  1846.         SetVBuf(fp, NULL, BUF_FULL, MY_FILE_BUF);
  1847.         /* So far so good. Setup a new project */
  1848.         if (!(npr = NewPro())) return NULL;
  1849.         strcpy(npr->Drawer,Drawer);
  1850.         strcpy(npr->Name,Name);
  1851.  
  1852.         /* Make a call to RFFParse */
  1853.         if ((retval = RFFParse(npr,fp)) < 0) {
  1854.                 ShowError(retval,fullname);
  1855.                 Close(fp);
  1856.                 DeletePro(npr);
  1857.                 return NULL;
  1858.         }
  1859.  
  1860.         /* Now we waste the old project and make the new project the current one */
  1861.         DeletePro(CurrentPro);
  1862.         CurrentPro = npr;
  1863.  
  1864.         /* Open the window so the user can see the loading */
  1865.         if ((retval = OpenLayWin(npr, npr->CurrentLayout)) < 0) {
  1866.                 ShowError(retval,fullname);
  1867.                 Close(fp);
  1868.                 DeletePro(CurrentPro);
  1869.                 CurrentPro = NULL;
  1870.                 return NULL;
  1871.         }
  1872.         UpdateTitleBar(npr,GetAppStr(MSG_LOADING_WINMSG)); /* User feedback that a file is loading */
  1873.         BlockInput(CurrentPro->CurrentLayout->Window,TRUE);
  1874.  
  1875.         /* Do the loading. */           
  1876.         if (!(buf = AllocMem(LOADBUFFERSIZE, MEMF_ANY))) {
  1877.                 Close(fp);
  1878.                 SetProMode(npr,MODE_NORMAL);
  1879.                 FreeInput(CurrentPro->CurrentLayout->Window);
  1880.                 return NULL;
  1881.         }
  1882.  
  1883.         while (LoadRecord(fp,buf,npr,npr->CurrentRec)) {
  1884.                 if (!AddRecord(&npr->CurrentRec)) {
  1885.                         /* out of memory */
  1886.                         EasyLocRequest(npr->CurrentLayout->Window, &ES_MemWarn, NULL, NULL);
  1887.                         break;
  1888.                 }
  1889.                 npr->CurrentRec = npr->CurrentRec->Next;
  1890.                 npr->RecSum++;
  1891.                 npr->RecNum++;
  1892.         }
  1893.         Close(fp);
  1894.         FreeMem(buf,LOADBUFFERSIZE);
  1895.         KillRecord(npr); /* Handles everything except updates */
  1896.         JumpList(npr,-npr->RecNum); /* Start at top of file */
  1897.         SetProMode(npr,MODE_NORMAL);
  1898.         FreeInput(CurrentPro->CurrentLayout->Window);
  1899.         return npr;
  1900. }
  1901.  
  1902. BOOL HandleArgs(int argc, char *argv[])
  1903. {
  1904.         /* Handles incoming arguments and open files. Opens only one file for now */
  1905.         /* Handles ToolTypes and also works from CLI */
  1906.         /* Uses AmigaDOS ReadArgs which has template support from CLI */
  1907.  
  1908.         struct WBStartup *argmsg;
  1909.         struct WBArg *wb_arg;
  1910.         struct Pro *npr = NULL;
  1911.         char argdir[FMSIZE];    /* See dos.h */
  1912.  
  1913.         if (argc == 0) {        /* Running from WB  */
  1914.  
  1915.                 /* Get filename and drawername of icon to load */
  1916.                 argmsg = (struct WBStartup *)argv;
  1917.                 wb_arg = argmsg->sm_ArgList;            /* head of the arg list */
  1918.  
  1919.                 if (argmsg->sm_NumArgs > 1) {           /* File(s) exists, load first only */
  1920.                         wb_arg++;       /* Skip over main program to first file */
  1921.                         if (NULL != wb_arg->wa_Lock) {
  1922.                                 /* locks supported, change to the proper directory */
  1923.                                 NameFromLock(wb_arg->wa_Lock,argdir,sizeof(argdir)); /* Path */
  1924.                                 npr=LoadPro(argdir,wb_arg->wa_Name);
  1925.                         }
  1926.                         /* else do nothing as that filesystem doesn't support locks */
  1927.                 }
  1928.         }
  1929.         else { /* Running from CLI */
  1930.                 /* Handle CLI args */
  1931.                 if (MyArgArray[FILES]) {        /* There are at least one file to load */
  1932.                         /* Get argdir */
  1933.                         stcgfp(argdir,*(char **)MyArgArray[FILES]);
  1934.                         npr=LoadPro(argdir,FilePart(*(UBYTE **)MyArgArray[FILES]));
  1935.                 }
  1936.         }
  1937.         if (!CurrentPro) ByeBye();
  1938.         /* If no project was loaded, open empty win */
  1939.         if (!npr) if (OpenLayWin(CurrentPro, CurrentPro->CurrentLayout) < 0) ByeBye();
  1940.         UpdateTitleBar(CurrentPro, NULL);
  1941.         return TRUE;
  1942. }
  1943.  
  1944.  
  1945. void InitSerial(void)
  1946. {
  1947.         /* Set up serial device */
  1948.         /* Needs to be done AFTER the ToolTypes has been set by HandleArgs(); */
  1949.         if (!(SerialMP = CreatePort(0,0))) ByeBye();
  1950.         if (!(SerialIO = (struct IOExtSer *)
  1951.          CreateExtIO(SerialMP, sizeof(struct IOExtSer))))
  1952.                 ByeBye();
  1953.  
  1954.         SerialIO->io_SerFlags = SERF_SHARED; // Turn on shared mode
  1955.  
  1956.         if (OpenDevice((char *)MyArgArray[DEVICE],*(UBYTE *)MyArgArray[UNIT],
  1957.          (struct IORequest *)SerialIO,0)) {
  1958.                 EasyLocRequest(CurrentPro->CurrentLayout->Window,
  1959.                  &ES_DialFail, NULL, (char *)MyArgArray[DEVICE],
  1960.                  *(UBYTE *)MyArgArray[UNIT]);
  1961.                 CloseSerial();
  1962.         }
  1963. }
  1964.  
  1965. int DoDial(char *phonenumber)
  1966. {
  1967.         char ds[800];
  1968.         char *dialstring = ds;
  1969.         extern void __asm DialDTMF(register __a0 char *phonenumber,
  1970.                                                                                 register __d0 unsigned int speed);
  1971.         extern void __asm DialCCITT5(register __a0 char *phonenumber,
  1972.                                                                                 register __d0 unsigned int speed);
  1973.         
  1974.         if (!IsPhoneNumber(phonenumber)) {
  1975.                 DisplayBeep(Scr);
  1976.                 return RC_WARN;
  1977.         }
  1978.         /* Fix the eventual areacode stripping */
  1979.         if(!Strnicmp(phonenumber, (char *)MyArgArray[AREACODE],
  1980.          strlen((char *)MyArgArray[AREACODE])))
  1981.                 phonenumber += strlen((char *)MyArgArray[AREACODE]);
  1982.  
  1983.         sprintf(dialstring,"%s%s%s\r",
  1984.          (char *)MyArgArray[DIALPREFIX],
  1985.          phonenumber,
  1986.          (char *)MyArgArray[DIALPOSTFIX]);
  1987.  
  1988.         if (MyArgArray[TONEDIAL]) {
  1989.                 if (MyArgArray[CCITT5])
  1990.                         DialCCITT5(phonenumber, *(UBYTE *)MyArgArray[TONEDIALSPEED]);
  1991.                 else DialDTMF(phonenumber, *(UBYTE *)MyArgArray[TONEDIALSPEED]);
  1992.                 return RC_OK;
  1993.         }
  1994.  
  1995.         /* Init serial device if not initialized before */
  1996.         if (!SerialMP) InitSerial();
  1997.         if (!SerialMP) return RC_ERROR;  
  1998.         SerialIO->IOSer.io_Command = CMD_WRITE;
  1999.         SerialIO->IOSer.io_Length = -1; // Null terminated string
  2000.         SerialIO->IOSer.io_Data = dialstring;
  2001.         DoIO((struct IORequest *)SerialIO);     // Send data
  2002.         return RC_OK;
  2003. }
  2004.  
  2005.  
  2006. void DoSelect(struct Pro *Pr)
  2007. {
  2008.         /* Select records from a ListView with fields */
  2009.         struct Rec *rec;
  2010.         Select *s;
  2011.         BOOL again = TRUE;
  2012.  
  2013.         struct VisFldInfo *vf = GetVisFldInfo(CurrentPro->CurrentLayout, LastGad);
  2014.         s = Pr->CurrentLayout->Browser;
  2015.         if (!s) return; /* safety */
  2016.  
  2017.         UpdateRecord(Pr);
  2018.  
  2019.         /* Sort on the selected field first? */
  2020.         if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) DoSort(Pr, vf->Offset);
  2021.  
  2022.         if (!FixSelectSize(s, Pr->RecSum)) return;              /* For speed */
  2023.  
  2024.         /* Seek first record */
  2025.         for (rec = Pr->CurrentRec; rec->Prev; rec = rec->Prev);
  2026.  
  2027.         BlockInput(Pr->CurrentLayout->Window,TRUE);     /* First a sleep clock */
  2028.  
  2029.         /* Fill the Select object */
  2030.         if (vf->Gadget->GadgetID == STRING_KIND)        /* For sake of speed, CodeToText does this also */
  2031.                 for (; rec; rec = rec->Next) AddStringLast(s, GetFld(rec, vf->Offset));
  2032.  
  2033.         else    /* Cycle- and checkbox gadgets */
  2034.                 for (; rec; rec = rec->Next) AddStringLast(s, CodeToText(vf, GetFld(rec, vf->Offset)));
  2035.  
  2036.         s->SelIndex = Pr->RecNum;
  2037.  
  2038.         OpenSelect(s, Pr->CurrentLayout->Window, vf->Name, GetAppStr(MSG_BROWSE_MODE_SCRMSG));
  2039.         while (again) {
  2040.                 WaitPort(s->SelWnd->UserPort);
  2041.                 switch(HandleSelectIDCMP(s)) {
  2042.                         case SEL_SELECT :
  2043.                                 JumpList(Pr, s->SelIndex - Pr->RecNum);
  2044.                                 UpdateDragBar(Pr);
  2045.                                 UpdateWindow(Pr);
  2046.                                 break;
  2047.                         case SEL_OK :
  2048.                         case SEL_CANCEL :
  2049.                                 again = FALSE;
  2050.                                 break;
  2051.                         case SEL_HELP :
  2052.                                 EasyLocRequest(NULL, &ES_BrowseHelp, NULL, NULL);
  2053.                                 break;
  2054.                 }
  2055.         }
  2056.         FreeInput(Pr->CurrentLayout->Window);
  2057.         CloseSelect(s);
  2058.         RemoveAllStrings(s);
  2059. }
  2060.  
  2061.  
  2062. /*
  2063.  * Some more security functions
  2064.  */
  2065.  
  2066. char *stripLF(char *s)
  2067. {
  2068.         char *start;
  2069.         for (start = s; *s; s++) if (*s == '\n') *s = '\0';
  2070.         return start;
  2071. }
  2072.  
  2073. BOOL rightKey(BPTR fp)
  2074.         /* Security is turned off as the source is released.
  2075.          * I only ensure that registered users get their name displayed correctly.
  2076.          */
  2077. {
  2078. //      char correctPassWord[12];
  2079.         char userName[50];
  2080.         char userPassWord[50];
  2081.         char idBuf[10];
  2082.         
  2083.         if (FGets(fp, userName, 40) &&
  2084.                  FGets(fp, idBuf, 10) &&
  2085.                  FGets(fp, userPassWord, 40)) {
  2086.  
  2087.                 stripLF(userName);
  2088.                 stripLF(idBuf);
  2089.                 stripLF(userPassWord);
  2090.                 
  2091.                 strcpy(UserName, userName);
  2092.                 UserID = atoi(idBuf);
  2093.  
  2094.                 return TRUE;
  2095.         }
  2096. }
  2097.  
  2098. BOOL checkKeyFile(void)
  2099. {
  2100.         /* Security is turned off as the source is released.
  2101.          * I only ensure that registered users get their name displayed correctly.
  2102.          */
  2103.  
  2104.         BPTR fp;
  2105.  
  2106.         if (((fp = Open("PROGDIR:db.key", MODE_OLDFILE)) ||
  2107.                  (fp = Open("l:db.key", MODE_OLDFILE)) ||
  2108.                  (fp = Open("s:db.key", MODE_OLDFILE))) &&
  2109.                  rightKey(fp)) {
  2110.                 PassWordOk = TRUE;
  2111.                 Close(fp);
  2112.                 return TRUE;
  2113.         }
  2114.         if (fp) Close(fp);
  2115.         return FALSE;
  2116. }
  2117.  
  2118. /**********************************************************************/
  2119. /*                            Read Prefs                              */
  2120. /**********************************************************************/
  2121.  
  2122. /*
  2123.  
  2124. #define MAX_PREFS_LEN 512
  2125. #define DB_PREFS "db.prefs"
  2126.  
  2127. char   *prefs;
  2128. struct RDArgs *rda;
  2129. struct RDArgs *rdargs;
  2130.  
  2131.   if(prefs = getenv(DB_PREFS))
  2132.     {
  2133.     prefs = realloc(prefs, strlen(prefs)+1);
  2134.     strcat(prefs, "\n");
  2135.  
  2136.     if(rda = AllocDosObject(DOS_RDARGS, TAG_DONE))
  2137.        {
  2138.        rda->RDA_Source.CS_Buffer = prefs;
  2139.        rda->RDA_Source.CS_Length = strlen(prefs);
  2140.        rda->RDA_Source.CS_CurChr = 0;
  2141.        rda->RDA_Flags |= RDAF_NOPROMPT;
  2142.  
  2143.        if(rdargs = ReadArgs(MyTemplate, PrefsArgArray, rda))
  2144.          {
  2145.          FreeArgs(rdargs);
  2146.          }
  2147.        else
  2148.          {
  2149.          DisplayBeep(NULL);
  2150.          }
  2151.        FreeDosObject(DOS_RDARGS, rda);
  2152.        }
  2153.      else
  2154.        {
  2155.        DisplayBeep(NULL);
  2156.        }
  2157.     free(prefs);
  2158.     }
  2159. */
  2160.  
  2161. /**********************************************************************/
  2162. /*                                Init                                */
  2163. /**********************************************************************/
  2164.  
  2165. void Init(int argc, char *argv[])
  2166. {
  2167.         /* First open all libraries (SAS C 6.5x handles this automatically) */
  2168.  
  2169.         UBYTE *tooltype;
  2170.         BPTR lock;
  2171.         
  2172.         if ((IntuitionBase = (struct IntuitionBase *)
  2173.                 OpenLibrary("intuition.library",37)) == NULL) ByeBye();
  2174.  
  2175.         if ((GfxBase = (struct GfxBase *)
  2176.                 OpenLibrary("graphics.library",37)) == NULL) ByeBye();
  2177.  
  2178.                 /* For commodities tooltypes, and icon creation */
  2179.         if ((IconBase = OpenLibrary("icon.library",37)) == NULL) ByeBye();
  2180.  
  2181.         if ((CxBase = OpenLibrary("commodities.library",37)) == NULL) ByeBye();
  2182.         if ((AslBase = OpenLibrary("asl.library",37)) == NULL) ByeBye();
  2183.         if ((GadToolsBase = OpenLibrary("gadtools.library",37)) == NULL) ByeBye();
  2184.         if (!(UtilityBase = OpenLibrary("utility.library",37))) ByeBye();
  2185.         if (!(WorkbenchBase = OpenLibrary("workbench.library", 37))) ByeBye();
  2186.         if (!(IFFParseBase = OpenLibrary("iffparse.library", 37))) ByeBye();
  2187.         if (TextFieldBase = OpenLibrary(TEXTFIELD_NAME, TEXTFIELD_VER)) {
  2188.                 TextFieldClass = TEXTFIELD_GetClass();
  2189.         }
  2190.         RexxSysBase = OpenLibrary(RXSNAME,0L);
  2191.  
  2192.         /* Do the argument check, and possible fail now */
  2193.  
  2194.         if(argc == 0)   /* WB */
  2195.                         {
  2196.  
  2197.                 TTypes = ArgArrayInit(argc, argv);
  2198.                 if (tooltype = FindToolType(TTypes,"DEVICE"))
  2199.                         MyArgArray[DEVICE] = (LONG)tooltype;
  2200.                 if (tooltype = FindToolType(TTypes,"UNIT"))
  2201.                         *(UBYTE *)MyArgArray[UNIT] = atoi(tooltype);
  2202.                 if (tooltype = FindToolType(TTypes,"DIALPREFIX"))
  2203.                         MyArgArray[DIALPREFIX] = (LONG)tooltype;
  2204.                 if (tooltype = FindToolType(TTypes,"DIALPOSTFIX"))
  2205.                         MyArgArray[DIALPOSTFIX] = (LONG)tooltype;
  2206.                 if (tooltype = FindToolType(TTypes,"AREACODE"))
  2207.                         MyArgArray[AREACODE] = (LONG)tooltype;
  2208.                 if (tooltype = FindToolType(TTypes,"PUBSCREEN"))
  2209.                         MyArgArray[PUBSCREEN] = (LONG)tooltype;
  2210.                 if (tooltype = FindToolType(TTypes,"FONTNAME"))
  2211.                         MyArgArray[FONTNAME] = (LONG)tooltype;
  2212.                 if (tooltype = FindToolType(TTypes,"FONTSIZE"))
  2213.                         *(int *)MyArgArray[FONTSIZE] = atoi(tooltype);
  2214.                 if (tooltype = FindToolType(TTypes,"NOICONS"))
  2215.                         MyArgArray[NOICONS] = TRUE;
  2216.                 if (tooltype = FindToolType(TTypes,"NOSPEEDRENDER"))
  2217.                         MyArgArray[NOSPEEDRENDER] = TRUE;
  2218.                 if (tooltype = FindToolType(TTypes,"NORETURNSTEP"))
  2219.                         MyArgArray[NORETURNSTEP] = TRUE;
  2220.                 if (tooltype = FindToolType(TTypes,"NOSERIAL"))
  2221.                         MyArgArray[NOSERIAL] = TRUE;
  2222.                 if (tooltype = FindToolType(TTypes,"HORIZBAR"))
  2223.                         MyArgArray[HORIZBAR] = TRUE;
  2224.                 if (tooltype = FindToolType(TTypes,"ESCQUIT"))
  2225.                         MyArgArray[ESCQUIT] = TRUE;
  2226.                 if (tooltype = FindToolType(TTypes,"TONEDIAL"))
  2227.                         MyArgArray[TONEDIAL] = TRUE;
  2228.                 if (tooltype = FindToolType(TTypes,"TONEDIALSPEED"))
  2229.                         *(UBYTE *)MyArgArray[TONEDIALSPEED] = atoi(tooltype);
  2230.                 if (tooltype = FindToolType(TTypes,"CCITT5"))
  2231.                         MyArgArray[CCITT5] = TRUE;
  2232.                 if (tooltype = FindToolType(TTypes,"MAKEBACKUP"))
  2233.                         MyArgArray[MAKEBACKUP] = TRUE;
  2234.                 if (tooltype = FindToolType(TTypes,"LOCALESORT"))
  2235.                         MyArgArray[LOCALESORT] = TRUE;
  2236.                 if (tooltype = FindToolType(TTypes,"HIGHLABEL"))
  2237.                         MyArgArray[HIGHLABEL] = TRUE;
  2238.                 if (tooltype = FindToolType(TTypes,"NOBORDER"))
  2239.                         MyArgArray[NOBORDER] = TRUE;
  2240.                 if (tooltype = FindToolType(TTypes,"DEFPATTERN"))
  2241.                         MyArgArray[DEFPATTERN] = (LONG)tooltype;
  2242.                 if (tooltype = FindToolType(TTypes,"DEFREXXPATTERN"))
  2243.                         MyArgArray[DEFREXXPATTERN] = (LONG)tooltype;
  2244.  
  2245.                 }
  2246.         else
  2247.                         {       /* CLI */
  2248.             if(!(MyRDArgs = ReadArgs(MyTemplate,MyArgArray,NULL)))
  2249.                                 ByeBye();
  2250.                 }
  2251.  
  2252.         /* Now, lets fill untouched fields with preferences */
  2253. //              if(MyArgArray
  2254.  
  2255.  
  2256.         
  2257.         checkKeyFile(); /* Security */
  2258.  
  2259.         if (LocaleBase = OpenLibrary("locale.library",38)) {
  2260.                 LocaleInfo.li_LocaleBase = LocaleBase;
  2261.                 LocaleInfo.li_Catalog    = OpenCatalog(NULL,"db.catalog",
  2262.                  OC_Version, 3, TAG_DONE);
  2263.                 if (MyArgArray[LOCALESORT] && (MyLocale = OpenLocale(NULL))) {          
  2264.                         /* Nothing here yet */
  2265.                 }
  2266.         }
  2267.  
  2268.         /* For the Clipboard */
  2269.         if (!(Iff0 = AllocIFF())) ByeBye();
  2270.         if (!(Iff0->iff_Stream = (ULONG) OpenClipboard(0))) ByeBye();
  2271.         InitIFFasClip(Iff0);
  2272.  
  2273.         if (!(Iff1 = AllocIFF())) ByeBye();
  2274.         if (!(Iff1->iff_Stream = (ULONG) OpenClipboard(1))) ByeBye();
  2275.         InitIFFasClip(Iff1);
  2276.         
  2277.         /* Get programname and path for correct 'default tool' in icons */
  2278.         if (lock = GetProgramDir()) NameFromLock(lock, ProgramDirAndName,FMSIZE);
  2279.         AddPart(ProgramDirAndName,"db",FMSIZE);
  2280.         DataIcon.do_DefaultTool = ProgramDirAndName;
  2281.  
  2282.         if (SetupScreen()) ByeBye(); /* GadToolBox */
  2283.         if ((AWPort = CreateMsgPort()) == NULL) ByeBye();       /* AppWindow */
  2284.         if (RexxSysBase) if ((MyRexxPort = SetupRexxPort("DB")) == NULL) ByeBye();
  2285.  
  2286.         /* Get the users custom font */
  2287.         if (*(int *)MyArgArray[FONTSIZE] != -1) {       /* User wants a custom font */
  2288.                 if (!(DiskfontBase = OpenLibrary("diskfont.library", 37))) ByeBye();
  2289.                 UserTextAttr.ta_Name = (STRPTR)MyArgArray[FONTNAME];
  2290.                 UserTextAttr.ta_YSize = *(int *)MyArgArray[FONTSIZE];
  2291.                 UserTextFont = OpenDiskFont(&UserTextAttr);
  2292.         }
  2293.  
  2294.         /* Create one project and layout */
  2295.         if (!(CurrentPro = NewPro())) ByeBye();
  2296.         if (!NewLayout(CurrentPro)) ByeBye();
  2297.  
  2298.         HandleArgs(argc, argv); /* Read arguments (CLI/WB) and open window and file */
  2299.  
  2300. }
  2301.  
  2302. /**********************************************************************/
  2303. /*            Eventhandlers that GadToolBox calls directly            */
  2304. /**********************************************************************/
  2305.  
  2306. void VisFldSelected(struct Gadget *gad)
  2307. {
  2308.         CurrentPro->Modified |= RECMODIFIED;
  2309.         /* Update the Rexx current field offset now */
  2310.         CurrentPro->CurrentFldOffset = GetVisFldInfo(CurrentPro->CurrentLayout, gad)->Offset;
  2311. }
  2312.  
  2313.  
  2314. void DragGadgetSelected(void)
  2315. {
  2316.         switch (CurrentPro->Mode) {
  2317.         case MODE_NORMAL:       
  2318.                 UpdateRecord(CurrentPro);
  2319.                 JumpList(CurrentPro,DB_Msg.Code - CurrentPro->RecNum);
  2320.                 UpdateDragBar(CurrentPro);      /* This "snaps" the dragbar correctly */
  2321.                 UpdateWindow(CurrentPro);
  2322.                 break;
  2323.         case MODE_FIND:
  2324.         case MODE_SORT:
  2325.                 break;
  2326.         }
  2327. }
  2328.  
  2329.  
  2330. void DoKill(BOOL ask)
  2331. {
  2332.         /* If ask is FALSE then no questions will be asked, (used by DB_CUT) */ 
  2333.         struct Layout *lay = CurrentPro->CurrentLayout;
  2334.         struct VisFldInfo *vf=lay->FirstVisFldInfo;
  2335.         BOOL empty = TRUE;
  2336.  
  2337.         switch (CurrentPro->Mode) {
  2338.         case MODE_NORMAL:
  2339.                 for (; vf; vf = vf->Next) if (strlen(ReadVisFld(CurrentPro, vf))) empty = FALSE;
  2340.                 
  2341.                 if (!empty) if (DisplayWarnings && ask)
  2342.                         if (!EasyLocRequest(CurrentPro->CurrentLayout->Window,
  2343.                          &ES_KillWarn, NULL, NULL)) break;
  2344.  
  2345.                 if (KillRecord(CurrentPro) == TRUE) {
  2346.                         UpdateDragBar(CurrentPro);
  2347.                         UpdateWindow(CurrentPro);
  2348.                         CurrentPro->Modified |= PROMODIFIED;
  2349.                 }
  2350.                 else DisplayBeep(Scr);
  2351.                 break;
  2352.         case MODE_FIND:
  2353.                 /* Just clear the fields */
  2354.                 ClearRecord(CurrentPro->FindRec);
  2355.                 UpdateGadgets(CurrentPro);
  2356.                 break;
  2357.         case MODE_SORT:
  2358.                 ClearRecord(CurrentPro->SortRec); /* InitSortRecord(CurrentPro); */
  2359.                 UpdateGadgets(CurrentPro);
  2360.                 break;
  2361.         }
  2362.  
  2363. }
  2364.  
  2365. int DB_KILL( void )
  2366. {
  2367.         /* routine when (sub)item "Kill" is selected. */
  2368.         DoKill(TRUE);
  2369.         return 0;
  2370. }
  2371.  
  2372. int DB_NEW( void )
  2373. {
  2374.         /* routine when (sub)item "New" is selected. */
  2375.         UpdateRecord(CurrentPro);
  2376.         if      (CurrentPro->Modified & PROMODIFIED)  /* File modified */  
  2377.                 if      (!EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_NewWarn, NULL, NULL)) return 0;
  2378.  
  2379.         if (ClearPro(CurrentPro) == FALSE) ByeBye();
  2380.         strcpy(CurrentPro->Name,GetAppStr(MSG_UNTITLED_PRO));
  2381.         /* We save the current drawer as the user will probably want that */
  2382.         UpdateDragBar(CurrentPro);
  2383.         UpdateWindow(CurrentPro);
  2384.  
  2385.         return 0;
  2386. }
  2387.  
  2388. int DB_OPEN( void )
  2389. {
  2390.         /* routine when (sub)item "Open..." is selected. */
  2391.    struct FileRequester *fr;
  2392.  
  2393.         /* NewPro will be called which in turn calls SetProMode so we don't have to */
  2394.  
  2395.         /* By supplying the dimension tags to AllocAslRequest, PD programs like */
  2396.         /* SetASLDim may modify the size to the users preference */
  2397.    fr = AllocAslRequest(ASL_FileRequest, frtags);
  2398.  
  2399.         if (AslRequestTags(fr,ASLFR_Window,CurrentPro->CurrentLayout->Window,
  2400.          ASLFR_SleepWindow, TRUE,
  2401.          ASLFR_TitleText,GetAppStr(MSG_OPEN_ASLREQ_TITLE),
  2402.          ASLFR_InitialDrawer, CurrentPro->Drawer,
  2403.          ASLFR_InitialFile, CurrentPro->Name,
  2404.          ASLFR_InitialPattern, CurrentPro->Pattern,
  2405.          TAG_DONE)) LoadPro(fr->fr_Drawer,fr->fr_File);
  2406.         
  2407.         FreeAslRequest(fr);
  2408.         if (!CurrentPro) ByeBye();
  2409.         return 1;       /* Old window closed, GadToolBox must ignore extra menuevents */
  2410. }
  2411.  
  2412. int DB_RELOAD( void )
  2413. {
  2414.         LoadPro(CurrentPro->Drawer, CurrentPro->Name);
  2415.         if (!CurrentPro) ByeBye();
  2416.         return 1;       /* Old window closed, GadToolBox must ignore extra menuevents */
  2417. }
  2418.  
  2419. int DB_SAVEAS( void )
  2420. {
  2421.         /* routine when (sub)item "Save as..." is selected. */
  2422.         Save(CurrentPro,SAVE_PRO);
  2423.         return 0;
  2424. }
  2425.  
  2426. int DB_SAVE( void )
  2427. {
  2428.         /* routine when (sub)item "Save" is selected. */
  2429.          {
  2430.                 if (Stricmp(CurrentPro->Name,GetAppStr(MSG_UNTITLED_PRO))) /* File saved before */
  2431.                         SavePro(CurrentPro,CurrentPro->Drawer,CurrentPro->Name,SAVE_PRO, FALSE);
  2432.                 else DB_SAVEAS();
  2433.         }
  2434.         return 0;
  2435. }
  2436.  
  2437. int DB_OUTPUT_VIEW( void )
  2438. {
  2439.         /* routine when (sub)item "Output view..." is selected. */
  2440.         Save(CurrentPro,SAVE_VIEW);
  2441.         return 0;
  2442. }
  2443.  
  2444. int DB_OUTPUT_VIEW_WN( void )
  2445. {
  2446.         /* routine when (sub)item "Output view with names..." is selected. */
  2447.         Save(CurrentPro,SAVE_VIEW_WN);
  2448.         return 0;
  2449. }
  2450.  
  2451. int DB_OUTPUT_TAB_ASCII( void )
  2452. {
  2453.         /* routine when (sub)item "Output Tab ASCII..." is selected. */
  2454.         Save(CurrentPro,SAVE_TAB_ASCII);
  2455.         return 0;
  2456. }
  2457.  
  2458. int DB_OUTPUT_COMMA_ASCII( void )
  2459. {
  2460.         /* routine when (sub)item "Output Comma ASCII..." is selected. */
  2461.         Save(CurrentPro,SAVE_COMMA_ASCII);
  2462.         return 0;
  2463. }
  2464.  
  2465. int DB_ABOUT( void )
  2466. {
  2467.         /* routine when (sub)item "About..." is selected. */
  2468.         if (!EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_About, NULL, 
  2469.          &Version[9], MyRexxPortName, UserName, UserID))
  2470.                 if (!EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_MoreAbout, NULL, NULL))
  2471.                         EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_MH_RFF, NULL, NULL);
  2472.  
  2473.         return 0;
  2474. }
  2475.  
  2476. int DB_QUIT( void )
  2477. {
  2478.         /* routine when (sub)item "Quit" is selected. */
  2479.         HandleQuit(CurrentPro);
  2480.         return 0;
  2481. }
  2482.  
  2483. int DB_COPY( void )
  2484. {
  2485.         /* routine when (sub)item "Copy" is selected. */
  2486.         UpdateRecord(CurrentPro);
  2487.         if (!CopyToClipboard(CurrentPro)) DisplayBeep(Scr);
  2488.         return 0;
  2489. }
  2490.  
  2491. int DB_CUT( void )
  2492. {
  2493.         /* routine when (sub)item "Cut" is selected. */
  2494.         DB_COPY();
  2495.         DoKill(FALSE);
  2496.         return 0;
  2497. }
  2498.  
  2499. int DB_PASTE( void )
  2500. {
  2501.         /* routine when (sub)item "Paste" is selected. */
  2502.         struct Rec *rp, *crp;
  2503.  
  2504.         switch (CurrentPro->Mode) {
  2505.         case MODE_NORMAL:       
  2506.                         if (!(rp = NewRecord())) {
  2507.                                 EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_MemWarn, NULL, NULL);
  2508.                                 break;
  2509.                         }
  2510.                         if (!PasteFromClipboard(CurrentPro, rp)) {
  2511.                                 DeleteRecord(&rp);
  2512.                                 break;
  2513.                         }
  2514.                         /* Everything ok, now link it */
  2515.                         crp = CurrentPro->CurrentRec;
  2516.                         rp->Next = crp->Next;                                   /* Curr  New->Next */
  2517.                         crp->Next = rp;                                                 /* Curr->New  Next */
  2518.                         rp->Prev = crp;                                                 /* Curr<-New  Next */
  2519.                         if (rp->Next) rp->Next->Prev = rp;      /* Curr  New<-Next */
  2520.  
  2521.                         UpdateRecord(CurrentPro);
  2522.                         CurrentPro->CurrentRec = CurrentPro->CurrentRec->Next;
  2523.                         CurrentPro->RecSum++;
  2524.                         CurrentPro->RecNum++;
  2525.                         UpdateDragBar(CurrentPro);
  2526.                         UpdateWindow(CurrentPro);
  2527.                         CurrentPro->Modified |= PROMODIFIED;
  2528.                         break;
  2529.         case MODE_FIND:
  2530.                 PasteFromClipboard(CurrentPro, CurrentPro->FindRec);
  2531.                 UpdateGadgets(CurrentPro);
  2532.                 break;
  2533.         case MODE_SORT:
  2534.                 PasteFromClipboard(CurrentPro, CurrentPro->SortRec);
  2535.                 UpdateGadgets(CurrentPro);
  2536.                 break;
  2537.         }
  2538.         return 0;
  2539. }
  2540.  
  2541. __inline static BOOL OkStrGad(struct Gadget *g) /* Duplicate from dbGUI.c */
  2542. {
  2543.         return (BOOL)(g->Flags & GFLG_TABCYCLE && !(g->Flags & GFLG_DISABLED));
  2544. }
  2545.  
  2546. int DB_ADD( void )
  2547. {
  2548.         struct VisFldInfo *vf;
  2549.         /* routine when (sub)item "Add" is selected. */
  2550.         switch (CurrentPro->Mode) {
  2551.         case MODE_NORMAL:
  2552.                 if (AddRecord(&CurrentPro->CurrentRec)) {
  2553.                         UpdateRecord(CurrentPro);
  2554.                         CurrentPro->CurrentRec = CurrentPro->CurrentRec->Next;
  2555.                         CurrentPro->RecSum++;
  2556.                         CurrentPro->RecNum++;
  2557.                         UpdateDragBar(CurrentPro);
  2558.                         UpdateWindow(CurrentPro);
  2559.  
  2560.                         for (vf = CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next) {
  2561.                                 if (OkStrGad(vf->Gadget)) {
  2562.                                         LastGad = vf->Gadget;
  2563.                                         VisFldSelected(vf->Gadget);
  2564.                                         ActivateGadget(vf->Gadget, CurrentPro->CurrentLayout->Window, NULL);
  2565.                                         break;
  2566.                                 }
  2567.                         }
  2568.                 }
  2569.                 else EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_MemWarn, NULL, NULL);
  2570.                 break;
  2571.         }
  2572.         return 0;
  2573. }
  2574.  
  2575. int LayIndex(struct Layout *first, struct Layout *current)
  2576. {
  2577.         int i;
  2578.         for (i=0; first && first != current; first = first->NextLayout, i++);
  2579.         return i;
  2580. }
  2581.  
  2582. int ChangeView(struct Layout *lay)
  2583. {
  2584.         /* This new version is a "hack". If there are problems, use older versions */
  2585.  
  2586.         /* If lay is NULL, use the menu instead (ARexx reason) */
  2587.         /* routine when one of the "View" items are selected. */
  2588.         /* We check if the menuitem really is checked first. */
  2589.         /* (User may play around with both mousebuttons, activating */
  2590.         /* menuitems without checking them.) */
  2591.  
  2592.         struct MenuItem *m;
  2593.         struct Layout *oldlay;
  2594.         int retval, viewnum;
  2595.         WORD ww, wh;
  2596.  
  2597.         oldlay = CurrentPro->CurrentLayout;
  2598.         if (!lay) {
  2599.                 m = ItemAddress(CurrentPro->Menu, DB_Msg.Code);
  2600.                 if (!(m->Flags & CHECKED)) return 0;
  2601.                 viewnum = ITEMNUM(DB_Msg.Code);
  2602.                 for (lay = CurrentPro->FirstLayout; viewnum; viewnum--, lay = lay->NextLayout);
  2603.         }
  2604.         else {
  2605.                 m = ItemAddress(CurrentPro->Menu, FULLMENUNUM(2, LayIndex(CurrentPro->FirstLayout, oldlay), NOSUB));
  2606.                 m->Flags &= ~CHECKED;   /* Delete old checkmark */
  2607.                 m = ItemAddress(CurrentPro->Menu, FULLMENUNUM(2, LayIndex(CurrentPro->FirstLayout, lay), NOSUB));
  2608.                 m->Flags |= CHECKED;    /* Set new checkmark */
  2609.         }
  2610.  
  2611.         UpdateRecord(CurrentPro);
  2612.         if (!lay || (lay==oldlay)) return 0;
  2613.  
  2614.         DeleteAllGadgets(oldlay, USE_MODE);
  2615.         
  2616.         CurrentPro->CurrentLayout = lay;
  2617.         lay->Window = oldlay->Window; /* We use the same window now */
  2618.         lay->AppWin = oldlay->AppWin;
  2619.         oldlay->Window = NULL;
  2620.         oldlay->AppWin = NULL;
  2621.  
  2622.         if ((retval = CalcAllPos(CurrentPro, CurrentPro->CurrentLayout, &ww, &wh)) < 0) {
  2623.                 ShowError(retval,NULL);
  2624.                 /* Try to fall back to the old layout */
  2625.                 CurrentPro->CurrentLayout = oldlay;
  2626.                 oldlay->Window = lay->Window; /* We use the same window now */
  2627.                 oldlay->AppWin = lay->AppWin; /* We use the same window now */
  2628.                 lay->Window = NULL;
  2629.                 lay->AppWin = NULL;
  2630.  
  2631.                 /* Correct the checkmark so it indicates this window */
  2632.                 
  2633.                 m->Flags &= ~CHECKED;   /* Delete old checkmark */
  2634.                 m = ItemAddress(CurrentPro->Menu, FULLMENUNUM(2, LayIndex(CurrentPro->FirstLayout, oldlay), NOSUB));
  2635.                 m->Flags |= CHECKED;    /* Set new checkmark */
  2636.  
  2637.                 if ((retval = CalcAllPos(CurrentPro, CurrentPro->CurrentLayout, &ww, &wh)) < 0) {
  2638.                         ShowError(retval,NULL);
  2639.                         ByeBye();
  2640.                 }
  2641.         }
  2642.         CreateAllGadgets(CurrentPro, CurrentPro->CurrentLayout, ww, wh, USE_MODE);
  2643.         AttachAllGadgets(CurrentPro->CurrentLayout, ww, wh, USE_MODE);
  2644.         UpdateWindow(CurrentPro);
  2645.         UpdateDragBar(CurrentPro);
  2646.  
  2647.         return 0;
  2648. }
  2649.  
  2650. int DB_VIEW() {
  2651.         return ChangeView(NULL);
  2652. }
  2653.  
  2654. /*
  2655. int DB_VIEW( void )
  2656. {
  2657.         /* routine when one of the "View" items are selected. */
  2658.         /* We check if the menuitem really is checked first. */
  2659.         /* (User may play around with both mousebuttons, activating */
  2660.         /* menuitems without checking them.) */
  2661.  
  2662.         struct MenuItem *m;
  2663.         struct Layout *lay, *oldlay;
  2664.         int i,pronum,retval;
  2665.  
  2666.         oldlay = CurrentPro->CurrentLayout;
  2667.         m = ItemAddress(CurrentPro->Menu, DB_Msg.Code);
  2668.         if (!(m->Flags & CHECKED)) return 0;
  2669.         
  2670.         UpdateRecord(CurrentPro);
  2671.  
  2672.         pronum = ITEMNUM(DB_Msg.Code);
  2673.         for (lay=CurrentPro->FirstLayout,i=0; lay && (i<pronum); lay=lay->NextLayout, i++);
  2674.         if (!lay || (lay==oldlay)) return 0;
  2675.         
  2676.         CloseLayWin(CurrentPro, oldlay);
  2677.         CurrentPro->CurrentLayout = lay;
  2678.         if ((retval = OpenLayWin(CurrentPro, CurrentPro->CurrentLayout)) < 0) {
  2679.                 ShowError(retval,NULL);
  2680.                 /* Try to fall back to the old layout */
  2681.                 CurrentPro->CurrentLayout = oldlay;
  2682.  
  2683.                 /* Correct the checkmark so it indicates this window */
  2684.                 for (lay=CurrentPro->FirstLayout,i=0; lay != oldlay; lay=lay->NextLayout, i++);
  2685.                 
  2686.                 m->Flags &= ~CHECKED;   /* Delete old checkmark */
  2687.                 m = ItemAddress(CurrentPro->Menu, FULLMENUNUM(2,i,NOSUB));
  2688.                 m->Flags |= CHECKED;    /* Set new checkmark */
  2689.  
  2690.                 if ((retval = OpenLayWin(CurrentPro, CurrentPro->CurrentLayout)) < 0) {
  2691.                         ShowError(retval,NULL);
  2692.                         ByeBye();
  2693.                 }
  2694.         }
  2695.         UpdateWindow(CurrentPro);
  2696.         UpdateDragBar(CurrentPro);
  2697.  
  2698.         return 1;       /* The old window is closed, so don't access more items */
  2699. }
  2700.  
  2701. */
  2702.  
  2703. int DB_FIND( void )
  2704. {
  2705.         /* routine when (sub)item "Find..." is selected. */
  2706. //      UpdateRecord(CurrentPro);       /* We are going to leave this record */
  2707.         SetProMode(CurrentPro,MODE_FIND);
  2708.         return 0;
  2709. }
  2710.  
  2711. int DB_FINDNEXT( void )
  2712. {
  2713.         /* routine when (sub)item "Find next" is selected. */
  2714.         if (CurrentPro->Mode != MODE_SORT) 
  2715.          FindRecord(CurrentPro,CurrentPro->RecNum+1,1);
  2716.         return 0;
  2717. }
  2718.  
  2719. int DB_SORT( void )
  2720. {
  2721.  
  2722.         /* routine when (sub)item "Sort" is selected. */
  2723. //      UpdateRecord(CurrentPro);       /* We are going to leave this record */
  2724.         SetProMode(CurrentPro,MODE_SORT);
  2725.         return 0;
  2726. }
  2727.  
  2728. int DB_DIAL( void )
  2729. {
  2730.         /* routine when (sub)item "Dial" is selected. */
  2731.         DoDial(ReadVisFld(CurrentPro, GetVisFldInfo(CurrentPro->CurrentLayout, LastGad)));
  2732.         return 0;
  2733. }
  2734.  
  2735. int DB_BROWSE( void )
  2736. {
  2737.         /* routine when (sub)item "Browse..." is selected. */
  2738.         if (LastGad) DoSelect(CurrentPro);
  2739.         else DisplayBeep(Scr);
  2740.         return 0;
  2741. }
  2742.  
  2743. int DB_WARNINGS( void )
  2744. {
  2745.         /* routine when (sub)item "Display warnings" is selected. */
  2746.  
  2747.         struct MenuItem *m;
  2748.         m = ItemAddress(CurrentPro->CurrentLayout->Window->MenuStrip, DB_Msg.Code);
  2749.         if (m->Flags & CHECKED) DisplayWarnings = TRUE;
  2750.         else DisplayWarnings = FALSE;
  2751.  
  2752.         return 0;
  2753. }
  2754.  
  2755. int DB_AZ( void )
  2756. {
  2757.         /* routine when (sub)item "A-Z" is selected. */
  2758.         /* We check if the menuitem really is checked first. */
  2759.         /* (User may play around with both mousebuttons on the menus, activating */
  2760.         /* menuitems without checking them.) */
  2761.         struct MenuItem *m;
  2762.         m = ItemAddress(CurrentPro->CurrentLayout->Window->MenuStrip, DB_Msg.Code);
  2763. //        if (m->Flags & CHECKED) SI.SortDir = SORT_DIR_AZ;
  2764.         SI.SortDir = SORT_DIR_AZ;
  2765.         return 0;
  2766. }
  2767.  
  2768. int DB_ZA( void )
  2769. {
  2770.         /* routine when (sub)item "Z-A" is selected. */
  2771.         /* We check if the menuitem really is checked first. */
  2772.         /* (User may play around with both mousebuttons on the menus, activating */
  2773.         /* menuitems without checking them.) */
  2774.         struct MenuItem *m;
  2775.         m = ItemAddress(CurrentPro->CurrentLayout->Window->MenuStrip, DB_Msg.Code);
  2776. //        if (m->Flags & CHECKED) SI.SortDir = SORT_DIR_ZA;
  2777.         SI.SortDir = SORT_DIR_ZA;
  2778.         return 0;
  2779. }
  2780.  
  2781. /*
  2782. int DB_SAVESETTINGS( void )
  2783. {
  2784.         /* routine when (sub)item "Save settings..." is selected. */
  2785.         return 0;
  2786. }
  2787. */
  2788.  
  2789. int DB_FIELD_DEFINITION( void )
  2790. {
  2791.         /* routine when (sub)item "Field definition" is selected. */
  2792.         return 0;
  2793. }
  2794.  
  2795. int DB_VIEW_DESIGN( void )
  2796. {
  2797.         /* routine when (sub)item "View design" is selected. */
  2798.         UpdateRecord(CurrentPro);
  2799.         Design(CurrentPro, CurrentPro->CurrentLayout);
  2800.         return 1; /* Window has been closed and a new has been opened */
  2801. }
  2802.  
  2803. int DB_EXECUTE_AREXX( void )
  2804. {
  2805.         /* routine when (sub)item "Execute ARexx script..." is selected. */
  2806.    struct FileRequester *fr;
  2807.         char fullname[FMSIZE];
  2808.         BOOL error = FALSE;
  2809.  
  2810.         if (!MyRexxPort) {
  2811.                 DisplayBeep(Scr);
  2812.                 return 0;
  2813.         }
  2814.  
  2815.         /* By supplying the dimension tags to AllocAslRequest, PD programs like */
  2816.         /* SetASLDim may modify the size to the users preference */
  2817.  
  2818. /*
  2819.    {
  2820.    struct TagItem *ti = FindTagItem(ASLFR_InitialPattern, frtags);
  2821.    if(ti)        ti->ti_Data = (ULONG)_DefRexxPattern;
  2822.    }
  2823. */
  2824.    fr = AllocAslRequest(ASL_FileRequest, frtags);
  2825.  
  2826.         if (AslRequestTags(fr,ASLFR_Window,CurrentPro->CurrentLayout->Window,
  2827.          ASLFR_SleepWindow, TRUE,
  2828.          ASLFR_TitleText,GetAppStr(MSG_EXECUTE_AREXX_ASLREQ_TITLE),
  2829.          ASLFR_InitialDrawer, CurrentPro->ARexxDrawer,
  2830.          ASLFR_InitialFile, CurrentPro->ARexxName,
  2831.          ASLFR_InitialPattern, CurrentPro->ARexxPattern,
  2832.          TAG_DONE)) {
  2833.                 strcpy(fullname, fr->fr_Drawer);
  2834.                 if (!AddPart(fullname, fr->fr_File, FMSIZE-1)) error = TRUE; /* incorrect filename */
  2835.         }
  2836.         else error = TRUE;
  2837.  
  2838.         strcpy(CurrentPro->ARexxDrawer, fr->fr_Drawer);
  2839.         strcpy(CurrentPro->ARexxName,fr->fr_File);
  2840.         strcpy(CurrentPro->ARexxPattern,fr->fr_Pattern);
  2841.  
  2842.         FreeAslRequest(fr);
  2843.  
  2844.         if (!error) SendRexxCommand(fullname);  
  2845.         return 0;
  2846. }
  2847.  
  2848.  
  2849. int DB_EXECUTE_AREXX_AGAIN( void )
  2850. {
  2851.         /* routine when (sub)item "Execute last ARexx script..." is selected. */
  2852.  
  2853.         char fullname[FMSIZE];
  2854.         BOOL error = FALSE;
  2855.  
  2856.         if (!MyRexxPort) {
  2857.                 DisplayBeep(Scr);
  2858.                 return 0;
  2859.         }
  2860.  
  2861.         strcpy(fullname, CurrentPro->ARexxDrawer);
  2862.         if(!AddPart(fullname, CurrentPro->ARexxName, FMSIZE-1))
  2863.                         error = TRUE; /* incorrect filename */
  2864.  
  2865.         if (!error) SendRexxCommand(fullname);  
  2866.         return 0;
  2867. }
  2868.  
  2869.  
  2870. void DoARexxMenu(int num)
  2871. {
  2872.         /* Execute an ARexx script on the menu. */
  2873.         int i;
  2874.         struct RxInfo *ri;
  2875.         struct RFFTag *tag;
  2876.  
  2877.         for (ri=CurrentPro->FirstRxInfo,i=0; ri && (i<num); ri=ri->Next, i++);
  2878.  
  2879.         if (ri && (tag = FindTag(&ri->RxTags, RXSTRING)))
  2880.                 SendRexxStrCommand(tag->Data);
  2881.         else if (ri && (tag = FindTag(&ri->RxTags, RXFILE)))
  2882.                 SendRexxCommand(tag->Data);
  2883. }
  2884.  
  2885. int DB_AREXX( void )
  2886. {
  2887.         /* routine when an item in the ARexx menu is selected. */
  2888.         int num;
  2889.  
  2890.         num = ITEMNUM(DB_Msg.Code) - 2;
  2891.         DoARexxMenu(num);
  2892.         return 0;
  2893. }
  2894.  
  2895. int DB_NewSize( void )
  2896. {
  2897.         /* routine for "IDCMP_NEWSIZE". */
  2898.         if (MyArgArray[NOBORDER]) return 0;
  2899.  
  2900.         SpeedRenderOff(CurrentPro->CurrentLayout);
  2901.         if (CurrentPro->CurrentLayout->FirstVisFldInfo)
  2902.         RefreshGList(CurrentPro->CurrentLayout->FirstVisFldInfo->Gadget, CurrentPro->CurrentLayout->Window, NULL, -1);
  2903.         if (!(SpeedRenderOn(CurrentPro->CurrentLayout))) ByeBye();
  2904.  
  2905.         return 0;
  2906. }
  2907.  
  2908. int DB_CloseWindow( void )
  2909. {
  2910.         /* routine for "IDCMP_CLOSEWINDOW". */
  2911.         switch (CurrentPro->Mode) {
  2912.                 case MODE_NORMAL:
  2913.                         HandleQuit(CurrentPro);
  2914.                         break;
  2915.                 case MODE_FIND: /* Abort find mode */
  2916.                 case MODE_SORT: /* Abort sort mode */
  2917. //                      UpdateRecord(CurrentPro);
  2918.                         SetProMode(CurrentPro,MODE_NORMAL);
  2919.                         break;
  2920.         }
  2921.         return 0;
  2922. }
  2923.  
  2924. int DB_MenuHelp( void )
  2925. {
  2926.         /* routine for "IDCMP_MENUHELP". */
  2927.         struct EasyStruct *HelpText = &ES_MH_NoHelp;
  2928.         USHORT menuNum, itemNum, subNum;
  2929.  
  2930.         menuNum = MENUNUM(DB_Msg.Code);
  2931.         itemNum = ITEMNUM(DB_Msg.Code);
  2932.         subNum  = SUBNUM(DB_Msg.Code);
  2933.  
  2934.         switch (menuNum) {
  2935.         case 0:      /* Project Menu */
  2936.                 switch (itemNum) {
  2937.                 case NOITEM: break;
  2938.                 case 0:
  2939.                         HelpText = &ES_MH_New;
  2940.                         break;
  2941.                 case 1:
  2942.                 case 3:
  2943.                 case 4: HelpText = &ES_MH_RFF; break;
  2944.                 case 5:
  2945.                         switch (subNum) {
  2946.                         case NOSUB: break;
  2947.                         case 0: HelpText = &ES_MH_Output_View; break;
  2948.                         case 1: HelpText = &ES_MH_Output_View_WN; break;
  2949.                         case 2: HelpText = &ES_MH_tab_ASCII; break;
  2950.                         case 3: HelpText = &ES_MH_comma_ASCII; break;
  2951.                         }
  2952.                         break;
  2953.                 }
  2954.                 break;
  2955.  
  2956.         case 1:      /* Edit Menu */
  2957.                 switch (itemNum) {
  2958.                 case NOITEM: break;
  2959.                 case 0:
  2960.                 case 1:
  2961.                 case 2: HelpText = &ES_MH_Clip; break;
  2962.                 case 6: HelpText = &ES_MH_Kill; break;
  2963.                 }
  2964.                 break;
  2965.         case 2:          /* View Menu */
  2966.                 break;
  2967.         case 3:      /* Action Menu */
  2968.                 switch (itemNum) {
  2969.                 case NOITEM: break;
  2970.                 case 0:
  2971.                 case 1: HelpText = &ES_FindHelp; break;
  2972.                 case 3: HelpText = &ES_SortHelp; break;
  2973.                 case 4: HelpText = &ES_DialHelp; break;
  2974.                 case 5: HelpText = &ES_BrowseHelp; break;
  2975.                 }
  2976.                 break;
  2977.  
  2978.         case 4:      /* Settings Menu */
  2979.                 switch (itemNum) {
  2980.                 case NOITEM: break;
  2981.                 case 0: HelpText = &ES_MH_Warnings; break;
  2982.                 case 1:
  2983.                         switch (subNum) {
  2984.                         case NOSUB: HelpText = &ES_MH_SortDir; break;
  2985.                         case 0: HelpText = &ES_MH_SortDir; break;
  2986.                         case 1: HelpText = &ES_MH_SortDir; break;
  2987.                         }
  2988.                         break;
  2989.                 case 3: HelpText = &ES_MH_Field_Definition; break;
  2990.                 case 4: HelpText = &ES_MH_View_Design; break;
  2991.                 }
  2992.                 break;
  2993.         case 5:         /* ARexx menu */
  2994.                 HelpText = &ES_MH_ARexx; break;
  2995.                 break;
  2996.  
  2997.         case NOMENU: /* No menu selected, can happen with IDCMP_MENUHELP */
  2998.                 break;
  2999.         }
  3000.         EasyLocRequest(CurrentPro->CurrentLayout->Window, HelpText, NULL, NULL);
  3001.         return 0;
  3002. }
  3003.  
  3004.  
  3005. int DB_SpecialAction(BOOL async)
  3006. {
  3007.         /* Routine called when user doubleclicks a stringgadget or hits LAMIGA+Key */
  3008.  
  3009.         LONG rxfiletagID, rxstrtagID;
  3010.         struct RFFTag *rxtag;
  3011.         BOOL success;
  3012.  
  3013.         if (!MyRexxPort || (CurrentPro->Mode != MODE_NORMAL)) return 0;
  3014.  
  3015.         if (!async) {   /* ie also use the AUTORX tags */
  3016.                 rxfiletagID = AUTORXFILE;
  3017.                 rxstrtagID = AUTORXSTRING;
  3018.         }
  3019.         else {
  3020.                 rxfiletagID = RXFILE;
  3021.                 rxstrtagID = RXSTRING;
  3022.         }
  3023.  
  3024.         if (rxtag = SearchTags(CurrentPro, NULL, NULL, rxstrtagID, rxfiletagID))
  3025.                 if (rxtag->ID == rxstrtagID) success = SendRexxStrCommand(rxtag->Data);
  3026.                 else success = SendRexxCommand(rxtag->Data);
  3027.  
  3028.         else if (async) 
  3029.                 DoSelect(CurrentPro); /* Select records from a ListView with fields */
  3030.  
  3031.         if (async) return 0;
  3032.         else if (success) {
  3033.                 do WaitPort(MyRexxPort);
  3034.                 while (!HandleRexxMessage(MyRexxPort));
  3035.         }
  3036.         return 0;
  3037. }
  3038.  
  3039.  
  3040. int DB_VanillaKey( void )
  3041. {
  3042.         /* routine for "IDCMP_VANILLAKEY". */
  3043.  
  3044.         struct VisFldInfo *vf;
  3045.         char shortcut, *cursor;
  3046.  
  3047.  
  3048.         switch (DB_Msg.Code) {
  3049.  
  3050.                 case '\r' :
  3051.                         switch (CurrentPro->Mode) {
  3052.                         case MODE_FIND: /* Start find */
  3053.                                 FindRecord(CurrentPro,0,1);
  3054.                                 break;
  3055.                         case MODE_SORT: /* Start sort */
  3056.                                 DoSort(CurrentPro, NORMAL_SORT);
  3057.                                 break;
  3058.                         case MODE_NORMAL:       /* Find next */
  3059.                                 if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) {
  3060.                                         FindRecord(CurrentPro,CurrentPro->RecNum-1,-1);
  3061.                                 } else FindRecord(CurrentPro,CurrentPro->RecNum+1,1);
  3062.                                 break;
  3063.                         }
  3064.                         break;
  3065.  
  3066.                 case VANILLA_ESC :
  3067.                         switch (CurrentPro->Mode) {
  3068.                                 case MODE_NORMAL:
  3069.                                         if (MyArgArray[ESCQUIT]) HandleQuit(CurrentPro);
  3070.                                         break;
  3071.                                 case MODE_FIND: /* Abort find mode */
  3072.                                 case MODE_SORT: /* Abort sort mode */
  3073. //                                      UpdateRecord(CurrentPro);
  3074.                                         SetProMode(CurrentPro,MODE_NORMAL);
  3075.                                         break;
  3076.                         }
  3077.                         break;
  3078.  
  3079.                 case VANILLA_DEL :
  3080.                         break;
  3081.  
  3082.                 case '\t' :
  3083.                         if (CurrentPro->CurrentLayout->FirstVisFldInfo)
  3084.                                 ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  3085.                         break;
  3086.  
  3087.                 case ' ' :      /* A fast way to switch to search mode and clear the fields */
  3088. //                      UpdateRecord(CurrentPro);
  3089.                         SetProMode(CurrentPro,MODE_FIND);
  3090.                         DoKill(TRUE);
  3091.                         break;
  3092.  
  3093.                 default :                /* Key-activation of gadgets or SpecialAction() */
  3094.                         for (vf = CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next) {
  3095.                                 for (shortcut = '\0', cursor = vf->Name; *cursor; cursor++) {
  3096.                                         if (*cursor == '_') {
  3097.                                                 shortcut = *(cursor+1);
  3098.                                                 break;
  3099.                                         }
  3100.                                 }
  3101.  
  3102.                                 if (ToUpper(DB_Msg.Code) == ToUpper(shortcut)) {
  3103.                                         if (DB_Msg.Qualifier & IEQUALIFIER_LCOMMAND) {
  3104.                                                 LastGad = vf->Gadget;
  3105.                                                 CurrentPro->CurrentFldOffset = vf->Offset;
  3106.                                                 DB_SpecialAction(TRUE);
  3107.                                         }
  3108.                                         else MyActivateGadget(vf, CurrentPro->CurrentLayout->Window);
  3109.                                         break;
  3110.                                 }
  3111.                         }
  3112.                         break;
  3113.         }
  3114.         return 0;
  3115. }
  3116.  
  3117. int DB_RawKey( void )
  3118. {
  3119.         /* routine for "IDCMP_RAWKEY". */
  3120.  
  3121.         /* dirty fix for HORIZBAR */
  3122.         if (MyArgArray[HORIZBAR]) {
  3123.                 switch (DB_Msg.Code) {
  3124.                         case RAW_LEFT : DB_Msg.Code = RAW_UP; break;
  3125.                         case RAW_RIGHT : DB_Msg.Code = RAW_DOWN; break;
  3126.                 }
  3127.         }       
  3128.         switch (DB_Msg.Code) {
  3129.  
  3130.                 case RAW_UP :
  3131.                         switch (CurrentPro->Mode) {
  3132.                         case MODE_NORMAL:
  3133.                                 if (CurrentPro->RecNum > 0) {
  3134.                                         UpdateRecord(CurrentPro);
  3135.                                         if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) {
  3136.                                                 JumpList(CurrentPro,-CurrentPro->RecNum);
  3137.                                         }
  3138.                                         else JumpList(CurrentPro, -1);
  3139.                                         UpdateDragBar(CurrentPro);
  3140.                                         UpdateWindow(CurrentPro);
  3141.                                 }
  3142.                                 if (ReactivateGad)
  3143.                                  ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  3144.                                 break;
  3145.                         }
  3146.                         break;
  3147.  
  3148.                 case RAW_DOWN:
  3149.                         switch (CurrentPro->Mode) {
  3150.                         case MODE_NORMAL:
  3151.                                 if (CurrentPro->RecNum < (CurrentPro->RecSum-1)) {
  3152.                                         UpdateRecord(CurrentPro);
  3153.                                         if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) {
  3154.                                                 JumpList(CurrentPro,CurrentPro->RecSum-CurrentPro->RecNum-1);
  3155.                                         }
  3156.                                         else JumpList(CurrentPro, 1);
  3157.                                         UpdateDragBar(CurrentPro);
  3158.                                         UpdateWindow(CurrentPro);
  3159.                                 }
  3160.                                 if (ReactivateGad)
  3161.                                  ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  3162.                                 break;
  3163.                         }
  3164.                         break;
  3165.  
  3166.                 case RAW_TAB:
  3167.                         ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
  3168.                         break;
  3169.                 
  3170.                 case RAW_HELP:
  3171.                         switch (CurrentPro->Mode) {
  3172.                         case MODE_NORMAL:
  3173.                                 EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_NormalHelp, NULL, NULL);
  3174.                                 break;
  3175.                         case MODE_FIND:
  3176.                                 EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_FindHelp, NULL, NULL);
  3177.                                 break;
  3178.                         case MODE_SORT:
  3179.                                 EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_SortHelp, NULL, NULL);
  3180.                                 break;
  3181.                         }
  3182.         }
  3183.         if (DB_Msg.Code >= RAW_F1 && DB_Msg.Code <= RAW_F10)
  3184.                 DoARexxMenu(DB_Msg.Code - RAW_F1 + 1);
  3185.         return 0;
  3186. }
  3187.  
  3188.  
  3189. int DB_MouseButtons( void )
  3190. {
  3191.         /* routine for "IDCMP_MOUSEBUTTONS". */
  3192.         return 0;
  3193. }
  3194.  
  3195.  
  3196. /**********************************************************************/
  3197. /*        Eventhandlers that GadToolBox won't supply code for         */
  3198. /**********************************************************************/
  3199.  
  3200. int DB_MouseMove( void )
  3201. {
  3202.         /* Dragregeln rapporterar sitt läge i DB_Msg.Code */
  3203.         switch (CurrentPro->Mode) {
  3204.         case MODE_NORMAL:
  3205.                 UpdateRecord(CurrentPro);
  3206.                 JumpList(CurrentPro,DB_Msg.Code-CurrentPro->RecNum);
  3207.                 UpdateWindow(CurrentPro);
  3208.                 break;
  3209.         case MODE_FIND:
  3210.                 break;
  3211.         }
  3212.         return 0;
  3213. }
  3214.  
  3215. void HandleAppWindow(void)
  3216. /* This only loads one of possibly many shift-dropped icon files */
  3217. {
  3218.         struct AppMessage *AppMsg;
  3219.         struct WBArg *wb_arg;
  3220.         char argdir[FMSIZE];
  3221.  
  3222.         while (AppMsg = (struct AppMessage *) GetMsg(AWPort)) {
  3223.                 wb_arg = AppMsg->am_ArgList;
  3224.                 if (AppMsg->am_NumArgs > 0) {           /* At least one file */
  3225.                         if (wb_arg->wa_Lock) {
  3226.                                 /* locks supported, change to the proper directory */
  3227.                                 NameFromLock(wb_arg->wa_Lock,argdir,sizeof(argdir)); /* Path */
  3228.                                 LoadPro(argdir,wb_arg->wa_Name);
  3229.                         }       
  3230.                 }
  3231.                 ReplyMsg((struct Message *) AppMsg);
  3232.                 if (!CurrentPro) ByeBye();
  3233.         }
  3234.         /* It's nice to have the window activated also */
  3235.         ActivateWindow(CurrentPro->CurrentLayout->Window);
  3236. }
  3237.  
  3238. /**********************************************************************/
  3239. /*                                main                                */
  3240. /**********************************************************************/
  3241.  
  3242. void main(int argc, char *argv[])
  3243. {
  3244.         ULONG appwinsig, myrexxportsig=0, signals;
  3245.  
  3246.         Init(argc, argv); /* Open libraries and windows.. */
  3247.  
  3248.         appwinsig = 1L << AWPort->mp_SigBit;
  3249.         if (MyRexxPort) myrexxportsig = 1L << MyRexxPort->mp_SigBit;
  3250.  
  3251.         /* Handle IDCMP events */
  3252.         for (;;) {
  3253.                 /* GadToolBox won't wait */
  3254.                 signals = Wait(WinSig | appwinsig | myrexxportsig);
  3255.  
  3256.                 if (signals & WinSig) {
  3257.                         /* This function in turn calls almost all functions.. */
  3258.                         /* Note IDCMP_MOUSEMOVE case has to be added, se top of code */
  3259.                         HandleDB_IDCMP(CurrentPro->CurrentLayout);
  3260.  
  3261.                         switch ( DB_Msg.Class ) {
  3262.                                 case    IDCMP_REFRESHWINDOW:
  3263.                                         SpeedRenderOff(CurrentPro->CurrentLayout);
  3264.                                         UpdateGadgets(CurrentPro);
  3265.                                         if (!(SpeedRenderOn(CurrentPro->CurrentLayout))) ByeBye();
  3266.                                         break;
  3267.                         }
  3268.                 }
  3269.                 if (signals & appwinsig) {
  3270.                         HandleAppWindow();
  3271.                 }
  3272.                 if (signals & myrexxportsig)
  3273.                         HandleRexxMessage(MyRexxPort);
  3274.         }
  3275. }
  3276.